Take a simple table person:
CREATE TABLE person
(
id bigint,
name nvarchar(128),
age int
)
You can represent this in a REST interface:
GET /person
GET /person/5
PUT /person
POST /person/5
PATCH /person/5
DELETE /person/5
This interface would expect 2 parameters:
{
name: 'Joe',
age: 16,
}
You could then define an API that would expect those two parameters, and even make the age optional.
However, suppose you wanted to define a model on the client side that wanted to do fancy things with this person table, such as pulling all teenagers, how would you best represent this?
I suppose I could do something this, only support GET, and then arbitrarily require different parameters which matched the query needs:
GET /person/teenager
However, I don't know that this would properly meet all use cases. For example, I believe REST urls should only have nouns, and I am not sure how to put something like this into noun form:
GET /person/by-age
Any ideas / references / suggestions?
The most common way to constrain your person listing results is to use query parameters. You can define your query parameters in any way that is useful for your API. One example might be GET /person?age=13..20 to get only teenagers. Another example might be GET /person/?filter=age>=13,age<20.
Related
I am trying to construct URL for the REST API that needs to use complex resource identifier
e.g. Get specific Course
GET /Courses/{id}
where {id} = {TermId}/{SubjectId}/{SectionID}
Is it acceptable to format it as below or there is a better way?
/Courses/{TermId}/{SubjectId}/{SectionID}
It's rather not acceptable, because it introduces confusion to the clients that use the API you provided. Basically / (slash) indicates a new resource. In this particular case you have Courses resources which has a particular resource with TermId which in turn has SubjectId and so on. This is not readable and not what client expects. I see two possible solutions here:
Use combined key, separated with - or other URI-useable sign:
GET /Courses/{TermId}-{SubjectId}-{SectionID}
Just parse such key on the server side.
Use other URI
GET /Courses/{courseId}/Terms/{termId}/subjects/{subjectId}/sections/{sectionId}
There are also other ideas, the one you suggested doesn't seem useable.
As I see it, you have two reasonable options:
Use a compound key, as #Opal said
Use a surrogate key (an arbitrary key with no relation to your three unique constraints)
The advantage to (1) is that the URI is human-hackable - assuming that the user remembers the order to put the values in and what valid values can be. If a significant use case is going to be students using these URIs to find courses online they might like to skip the search step if they have all the relevant information and just punch those values into the URI. If your response type is HTML, this is not unreasonable.
The advantage to (2) is that it's not human-hackable - REST is about discovery through hypermedia. If the response type is JSON or XML, humans aren't going to be using these URIs directly.
I would suggest supporting the following endpoints:
GET /courses?termId={}&subjectId={}§ionId={}
// all three parameters are optional. returns all courses that match the
// specified criteria - either a subset of the data or the full course
// data for each result
GET /courses/{courseId}
I have REST API URL structure similar to:
/api/contacts GET Returns an array of contacts
/api/contacts/:id GET Returns the contact with id of :id
/api/contacts POST Adds a new contact and return it with an id added
/api/contacts/:id PUT Updates the contact with id of :id
/api/contacts/:id PATCH Partially updates the contact with id of :id
/api/contacts/:id DELETE Deletes the contact with id of :id
My question is about:
/api/contacts/:id GET
Suppose that in addition to fetching the contact by ID, I also want to fetch it by an unique alias.
What should be URI structure be if I want to be able to fetch contact by either ID or Alias?
If you're alias's are not numeric i would suggest using the same URI structure and figuring out if it's an ID or an alias on your end. Just like Facebook does with username and user_id. facebook.com/user_id or facebook.com/username.
Another approach would be to have the client use GET /contacts with some extra GET parameters as filters to first search for a contact and then looking up the ID from that response.
Last option i think would be to use a structure like GET /contacts/alias/:alias. But this would kinda imply that alias is a subresource of contacts.
The path and query part of IRIs are up to you. The path is for hierarchical data, like api/version/module/collection/item/property, the query is for non-hierarchical data, like ?display-fields="id,name,etc..." or ?search="brown teddy bear"&offset=125&count=25, etc...
What you have to keep in mind, that you are working with resources and not operations. So the IRIs are resource identifiers, like DELETE /something, and not operation identifiers, like POST /something/delete. You don't have to follow any structure by IRIs, so for example you could use simply POST /dashuif328rgfiwa. The server would understand, but it would be much harder to write a router for this kind of IRIs, that's why we use nice IRIs.
What is important that a single IRI always belongs only to a single resource. So you cannot read cat properties with GET /cats/123 and write dog properties with PUT /cats/123. What ppl usually don't understand, that a single resource can have multiple IRIs, so for example /cats/123, /cats/name:kitty, /users/123/cats/kitty, cats/123?fields="id,name", etc... can belong to the same resource. Or if you want to give an IRI to a thing (the living cat, not the document which describes it), then you can use /cats/123#thing or /users/123#kitty, etc... You usually do that in RDF documents.
What should be URI structure be if I want to be able to fetch contact
by either ID or Alias?
It can be /api/contacts/name:{name} for example /api/contacts/name:John, since it is clearly hierarchical. Or you can check if the param contains numeric or string in the /api/contacts/{param}.
You can use the query too, but I don't recommend that. For example the following IRI can have 2 separate meanings: /api/contacts?name="John". You want to list every contact with name John, or you want one exact contact. So you have to make some conventions about this kind of requests in the router of your server side application.
I would consider adding a "search" resource when you are trying to resolve a resource with the alias:
GET /api/contacts/:id
and
GET /api/contacts?alias=:alias
or
GET /api/contacts/search?q=:alias
First of all, the 'ID' in the URL doesn't have to be a numerical ID generated by your database. You could use any piece of data (including the alias) in the URL, as long as its unique. Of course, if you are using numerical ID's everywhere, it is more consistent to do the same in your contacts API. But you could choose to use the aliases instead of numeric IDs (as long as they are always unique).
Another approach would be, as Stromgren suggested, to allow both numeric IDs and aliases in the URL:
/api/contacts/123
/api/contacts/foobar
But this can obviously cause problems if aliases can be numeric, because then you wouldn't have any way to differentiate between an ID and a (numeric) alias.
Last but not least, you can implement a way of filtering the complete collection, as shlomi33 already suggested. I wouldn't introduce a search resource, as that isn't really RESTful, so I'd go for the other solution instead:
/api/contacts?alias=foobar
Which should return all contacts with foobar as alias. Since the alias should be unique, this will return 1 or 0 results.
I'm designing a RESTful API and I'm trying to work out how I could represent a predicate with OR an operator when querying for a resource.
For example if I had a resource Foo with a property Name, how would you search for all Foo resources with a name matching "Name1" OR "Name2"?
This is straight forward when it's an AND operator as I could do the following:
http://www.website.com/Foo?Name=Name1&Age=19
The other approach I've seen is to post the search in the body.
You will need to pick your own approach, but I can name few that seem to be pretty logical (although not without disadvantages):
Option 1.: Using | operator:
http://www.website.com/Foo?Name=Name1|Name2
Option 2.: Using modified query param to allow selection by one of the values from the set (list of possible comma-separated values):
http://www.website.com/Foo?Name_in=Name1,Name2
Option 3.: Using PHP-like notation to provide list instead of single string:
http://www.website.com/Foo?Name[]=Name1&Name[]=Name2
All of the above mentioned options have one huge advantage: they do not interfere with other query params.
But as I mentioned, pick your own approach and be consistent about it across your API.
Well one quick way to fixing that is to add an additional parameter that is identifying the relationship between your parameters wether they're an and or an or for example:
http://www.website.com/Foo?Name=Name1&Age=19&or=true
Or for much more complex queries just keep a single parameter and in it include your whole query by making up your own little query language and on the server side you would parse the whole string and extract the information and the statement.
I'm working on creating a REST API. Lets say the resource I'm serving is called object and it contains a number of properties.
Apart from requesting the entire set of objects like this
GET api.example.com/objects
I want to allow requesting a single object by providing either the objectid or objectname,
like this
GET api.example.com/objects?objectid=
GET api.example.com/objects?objectname=
What I'm confused about is, how should I handle a request like this?
GET api.example.com/objects?objectid=x&objectname=y
In this case, should I return a 400 Bad Request, or should one of the parameters take precedence over the other? How does REST define this behavior?
REST generally assumes there is a unique URL for a resource, so it would be:
GET api.example.com/objects/objectId
Parameters are commonly used for searching, so you would have something like:
GET api.example.com/objects?objectName=x
A better approach would be use a generic key in the parameter string to retrieve field values of your specific resource
GET api.example.com/objects/objectId?field=objectName,anotherField
It complements xpapad's suggestion, and can add scalable structure in how you define a consistent approach to your API design.
I use : Subsonic 3, SQL Server 2008, Json.Net
Here is my problem :
I have a house table with id,lot number, address, location, ownerid and an owner table with id,name, description.
I'd like to get only the owner name and address of house where location is "San Francisco".
How can I do this with Subsonic?
My problem is I can only get a typed list or a datareader, I don't understand how to only get an array or a simple list.
What is the best solution? Create a custom class ? Create a View ? Anything else ?
My aim is to then serialize the data to send it back to my application, but serialization is seriously long because of the numerous relationships (My example here is simplified, there are indeed : house - owner - city - country etc.), whereas I need only 2 fields...
Thank you
Take a look at Some Issues about Rob Conery's repository pattern ?, rob provides the answer to exactly what you're asking for.
If the information is only going to be used in one place, maybe use a struct with two fields?