When following a REST approach, which of the following GET requests is more correct:
v1/companies/10/employees/state=approved
v1/companies/10/employees?state=approved
There seems to be mixed use online.
Only the second approach makes sense to me. In a RESTful approach, you have to use the QueryString in order to filter the returned resources. In this case, add in your querystring the resource attributes that you want to use as filters. For example:
v1/companies/10/employees?state=approved&attribute2=value&attribute3=value
The first URI doesn't make any sense to me because you're doing a mix between URI and QueryString to filter the result.
v1/companies/10/employees/state=approved
Just to clarify, let's look at another example. The URI below only makes sense if "state" and "approved" are resources. But if they're only attributes from employee, then it's not RESTful. Remember, design your URIs considering that you're exposing resources rather than methods or actions.
v1/companies/10/employees/state/approved
I think it depends rather state is a resource or not. REST conventions are Controller/Resource/Sub -Resource, for example:
Books/Comics/SuperMan/FirstEditon rather than
Books/Comics/SuperMan?edition=FirstEdition
More readable, and indicates that FirstEdition is a resource rather than a state.
Related
My HTTP API has a method that updates resources found by filter. Practically it is a POST method, that utilizes a query string to find desired resources and transfers data in its body to update found resources:
POST /module/resources?field_1=abc&field_2=def&field_n=xyz
body: {
"desired_field":"desired_data"
}
I've heard it might be a code smell using a POST method and a query string together, but in the case presented above it seems perfectly reasonable to me.
Am I making wrong assumptions here?
Is it okay to use HTTP POST method with a query string, if a query string is used to find the resources that need to be updated?
Yes.
Am I making wrong assumptions here?
No.
The key ideas being that you, as the author of the resource, get to choose its identifier
REST relies instead on the author choosing a resource identifier that best fits the nature of the concept being identified. -- Fielding, 2000
the query is part of the resource identifier
The query component contains non-hierarchical data that, along with data in the path component (Section 3.3), serves to identify a resource within the scope of the URI's scheme and naming authority -- RFC 3986
and that the semantics of HTTP methods are standardized across all resources
Once defined, a standardized method ought to have the same semantics when applied to any resource, though each resource determines for itself whether those semantics are implemented or allowed. -- RFC 7231
When talking about resources, there's from a HTTP/REST perspective no difference between:
/article/1
/article?id=1
So if you do a GET request on either of these to get the article, you can do a PUT or PATCH on either of those to make changes.
However, the way many developers think of query parameters and POST bodies is often 'just a different way to send parameters'. This is incorrect, because they have a pretty distinct meaning, but using both at the same time may confuse some people.
So on a protocol level what you're doing is perfectly fine. I'd argue it's kind of elegant to use the URI as the locator and the body as the main message.
I am modeling blogging REST API which has resources Blog, Post and Comment with following URLs:
/api/blogs
/api/blogs/{blogId}
/api/blogs/{blogId}/posts
and I create separate endpoint for all Posts in and their Comment`s:
/api/posts
/api/posts/{postId}
/api/posts/{postId}/comments
Given that I have postId, what is the RESTful way to get Blog for a specific Post? I have three ideas:
1. /api/posts/{postId}/blog
2. /api/blogs/parent-of-post/{postId}
3. /api/blogs?postId={postId}
To me the 1. URL looks more "prettier" but the 2. option looks more "logical" since that endpoint (eg. /api/blogs/*) is generally for blogs resources.
The third option uses query string as parameter but the issue I have with it is that this endpoint would return different type of body depending on the parameter. Eg. without parameter /api/blogs returns a collection of Blog resources, while with parameter postId it would return just single instance of Blog. I am not sure if this is good thing to do (especially because I am using ASP.NET Core and C# which has strongly typed return objects, so implementation might be awkward).
what is the RESTful way to get Blog for a specific Post?
Real answer: anything you want.
REST doesn't care what spelling conventions you use for your resource identifiers. As long as your identifiers conform to the production rules described by RFC 3986, you are good to go.
/api/blogs?postId={postId}
This is a perfectly normal choice, and turns out to be a really convenient one when you want to use general purpose web browsers, because HTML forms already have standards that make it easy to create URI with this shape.
Your other two choices are fine; they lose a point for not being HTML form friendly, but it's still easy enough to describe these identifiers using a URI template.
The third option uses query string as parameter but the issue I have with it is that this endpoint would return different type of body depending on the parameter
General purpose API consumers do NOT assume that two resources are alike just because the spellings of their identifiers overlap each other.
Which is to say, from the outside, there is no implied relationship between
/api/blogs
/api/blogs/1
/api/blogs?postId=2
so the fact that they return different bodies really isn't going to be a surprise to a general purpose consumer.
Now, your routing framework may not support returning different types from the handlers for these resources (or, more likely, may not have any "nice" way to do the routing automatically), but that's an implementation detail deliberately hidden behind the REST API facade.
Similarly, the human beings that read your access log might prefer one spelling to another, to reduce their own cognitive load.
I knew some name conversions of REST API, for example resource name should be plural, using different HTTP method with same URI to perform different action on that resource, etc.
But as URI should reflect relationship of resources, I am a little confused. Take SO as a example, when update a existed comment of a answer, URI should looks like:
PUT /{contextPath}/questions/{questionId}/answers/{answerId}/comments/{commentId}
But I feel awkward when using this so-called standard URI because:
It's a little verbose, especially when the hierarchical is very
deep.
questionId and answerId is completely unnecessary here, since
commentId is sufficient for server to identify a comment record.
So what's the appropriate way to deal with this? should I always follow name conversions, or make some changes when the relationship hierarchical of resources is very deep?
I emphatically disagree that "URI should reflect relationship of resources".
URIs are pointers to resources. That's it. There are conventions for making them human-readable, and therefore easier to work with. There is certainly no hard-and-fast rule that relationships should be modeled on the URI path. Feel free to model resources in a flat, rather than hierarchical manner. Use links to model relationships between the resources, and query parameters to narrow down collections.
It gives you more Options without haveing to make extra requests.
Thus allowing you to call functions that might require say a questionId.
When you only have the commentId you have to first query your questionId.
Depending on what your functions require. If you had specific info on the previous page and have to use it again in the next why query it twice? Unless it is sensitive which an questionId clearly is not.
Thats my opinion on how you should look at your addoption of the standard
I would simplify the route/URI to:
PUT /comments/{commentId}
along with at the corresponding RequestBody, perhaps some sort of DTO.
The URI should not have to show the hierarchy all the way from the context path. It can be the shortest URI that can uniquely identify the resource
Which of the following URLs is more RESTful compliant when it comes to fetch only items that have a certain value for attribute?
GET: /items/attribute/{value}
GET: /items/findByAttribute?attribute={value}
GET: /items?attribute={value}
Having in mind that GET: /items returns all items.
Example
GET: /shirts/color/FF9900
GET: /shirts/findByColor?color=FF9900
GET: /shirts?color=FF9900
I think that the last option is the correct one ;-)
Here are some comments for the others:
Generally the path element right after the one that corresponds to the list resource is the identifier of the element. So if you use something at this level, it could be considered as an identifier...
You can have resource to manage a particular field but the URL would be something like /items/{itemid}/fieldname.
You shouldn't use "action names" within the URL (in your example findByAttribute). The HTTP method should correspond to the "action" itself. See this answer if you want to support several actions for an HTTP method: How to Update a REST Resource Collection.
There is a question about how to design search filter: How to desing RESTful advanced search/filter. I think that your use case if a bit simple and using query parameters matches for you.
Otherwise I wrote a post about the way to design a Web API. This could be useful for you. See this link: https://templth.wordpress.com/2014/12/15/designing-a-web-api/.
Hope it helps you,
Thierry
Most certainly this one
GET: /items?attribute={value}
Why?
GET: /items/attribute/{value} is wrong because with REST, url segments represent resources, attribute is not a resource
GET: /items/findByAttribute?attribute={value} is wrong for the same reason really. findByAttribute is not a resource
Using url queries to filter by attributes is perfectly fine, so go with that.
URI semantics are irrelevant to REST. It doesn't make sense to ask which URI is more RESTful. What makes an URI RESTful or not is how the client obtains it. If he's reading URI patterns in documentation and filling placeholders with values, it's not RESTful. If this is news for you, I recommend reading this.
With that in mind, all three examples can be RESTful if the server provided that URI template to the client as a link to query the collection resource filtering by that value, but 3 is definitely the best option since it follows a more conventional query syntax. I wouldn't use 2 since it implies a method call and it looks too RPC for my taste, and I wouldn't use 1 since it implies for a human that it will return only the attribute as a resource.
One approach says that you should keep your resource URL simple. We have verb in HTTP and resource name as path. So we can have:
GET /books/12
And if we want to fetch related collection, we might do:
GET /books/12/pages
On the other hand, there is a practice to use so-called resource verbs where you can fine-tune the verbs operation:
POST /books/12/bookmark
I would not use both approaches for my API. I tend to think that first approach is more correct (i.e. no verbs in resource name allowed), and to model the second approach we might use different entity, like:
POST /book-bookmarks/12/
or different id:
POST /bookmarks/12+book/
I know there is no true answer on this, but which one would be preferred? I would like to see some answers from people that actually went through design decisions like this one.
URI (or IRI) is a standard about indentifying resources. These resources can be web documents, real things, etc... In the current case they are web documents. Afaik. there is not standard about the URI structures, but URI standard along with HTTP standard suggest that you should use URIs and HTTP methods in a procedural way. So the HTTP verbs describe the procedure and the URIs identify the object of the procedure. Now you typically describe procedures with verbs and you typically describe objects with nouns. That's why it is logical to use only nouns in the URI structure, at least in the (hierarchical) path part of it.
(You usually can solve everything with the standard HTTP methods and proper nouns. Only in very special things can cause problems. In those cases I think it is better to use a new HTTP method than putting verbs into the URI. But that is really very rare. E.g. search with query string non compatible parameters e.g. files can be such a case. Another alternative approach in these cases to use POST and verbs in the URI.)