A question about REST uri design. In the official web api tutorial i have seen the following uri:
Get a list of books by publication date: /api/books/date/2013-02-16
Following the rest principles it's not better using the following uri?
/api/books?date=2013-02-16
Thanks
There are no hard rules about were parameters should go in this case. Some place them in the URL path some add them to the query string. Do note that in REST there is no emphasis placed on the way URLs should look like. People create them hierarchically because it makes sense to do so given their domain e.g.:
/api/books/ # all books
/api/books/100 # details about the book with id=100
/api/books/mystery # all books in the mystery category
On the other hand, /api/books/date/2013-02-16 is a little bit of a stretch, again because people reason about hierarchies of resources and most of the times model their APIs as such, so given that they would expect /api/books/date to also return some books in a larger category than /api/books/date/2013-02-16 does. But in this case it doesn't really make sense, so maybe that's why you find /api/books?date=2013-02-16 to be a more natural choice.
I would also prefer /api/books?date=2013-02-16 in this case. But again, there are no hard rules on what the better choice is, see for example this: REST API Best practices: Where to put parameters?
They are equal. According to the URI standard, the path contains the hierarchical part of the identifier while the query part contains the non-hierarchical part. Now in the case of map reducing a collection you can consider the filter both hierarchical and non-hierarchical depending on your taste.
Btw. I prefer the param:value solution in the path and ending the URIs of the collections (or reduced collections) with slash, so: /api/books/date:2013-02-16/, but afaik. that is just best practice, not standard... :-)
According to the uniform interface constraint of REST, you have to apply existing standards over custom solutions, that's why we follow the URI standard in this case...
Related
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 am building a RESTful API where I have a resource named solar_systems. solar_sytems has id(int), system_size(int), system_cost(int) columns with many other columns.
I understand that API endpoints will be-
/v1/solar-systems - for all systems
/v1/solar-systems/{id} - for a single system
And I have to pass query params for filter, search, sorting etc.
But what will be the best practice for API endpoints if I need some kind of custom data like if I need average system_cost for each system_size.
Will it be silly, if I use - /v1/solar-systems/average-system-cost?
Please I need your opinion from your experience.
It is not silly at all to use /v1/solar-systems/average-system-cost
It is easy to get caught up in the fact that technically the average-system-cost is not a resource. But it is a piece of data that is useful to retrieve. Ultimately the goal of REST is to make APIs that are understandable and readable. A specific endpoint that gets a useful piece of data definitely falls inside that.
Will it be silly, if I use /v1/solar-systems/average-system-cost?
The REST architecture doesn't enforce any URI design (see notes below). It's totally up to you to pick the URIs that better identify your resources.
However I would probably use query parameters to select the fields to be returned in the response. Something like /v1/solar-systems?fields=average-system-cost.
Note 1: The REST architectural style, described in the chapter 5 of Roy T. Fielding's dissertation, defines a set of constraints that must be followed by the applications that follow such architecture. However it says nothing about what the URLs must be like.
Note 2: On the other hand, the examples of a popular article written by Martin Fowler explaining a model defined by Leonard Richardson suggest a URL structure that looks friendly and easy to read.
I have been doing RESTful APIs for quite a bit (exposing and consuming 3rd parties) and I see two following patterns popping up here and there. Each has pros and cons and neither is "clean" in my opinion.
So the situation is: you have a collection resource (e.g. "assets") and you want to expose some additional resources within a collection (e.g. subresources of the collection itself, not the asset, like aggregated view endpoint or some commands).
Two patterns I see are:
People create a RESTful collection resource like /assets/${asset-id} and expose everything else they need like GET /assets/owned, GET /assets/summary, POST /assets/recheck-inventory. This looks neat and concise but introduces a clash between ${asset-id} and nouns of sub-resource URLs (e.g. asset12345 and summary are in the same place in the URL).
Others do /assets/items/${asset-id} and expose everything like GET /assets/owned, GET /assets/summary and so on. This is cleaner from routing perspective and a bit more future-proof, but adds an extra noun in the route, which leads to confusion when people are trying to do POST /assets for example.
The "best practice" guidelines I went through thus far avoid the question altogether. I also understand that REST is a convention and not the standard, and there is a universal "it depends" answer. Still, I feel like there got to be a generic recommendation here.
Hence the question is: which of two you would use?
UPDATE: to clarify, let us assume that:
/assets/owned contains entities of different types, not assets, so it is not a query and you can GET/POST/DELETE items in it.
/assets/summary is an aggregation document (e.g. report with quantities for example)
/assets/recheck-inventory is a command (i.e. POST only)
Also, we want to stick with REST principles:
route's path shall identify an entity and its state uniquely.
query parameters alter which elements are returned, but do not change the payload format.
headers are for protocol-level information and do not change service logic (i.e. presentation, security, caching, etc.)
I don't like these approaches either, but be aware, that REST does not put constraint on how to design URI structure, so you can do whatever you feel right. Apparently the developers of these webservices felt this approach right.
I would do something like the following with your URIs, since I like flat URIs much better.
/assets/items/${asset-id}
-> /assets/${asset-id}
/assets/owned
-> /assets/?owned
-> /assets/?owned=true
/assets/summary
-> /assets-summary
-> /assets/ + "Prefer: return=minimal"
You can find more about the prefer header here, but be aware, that you need to register it by the vary header if you want it to be a secondary cache key.
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
I have to decide on a pagination strategy for returning results from a list. In particular, I am considering two approaches:
Example that lists results from 50 to 75:
Using query params: GET /items?start=50&limit=25
Pros
Widely used
Bookmarkable
Cons
You will probably need to encode the URL ("&" character) to place it on XML response (complying with HATEOAS), and in that case the URL will not be very human friendly.
Embedded on the URL (page as a sub resource): GET /items/from-page-50-limited-to-25
Pros
As human readable as needed (not required but seems like a good thing)
No encoding necessary ever
Cons
A little harder to build the URL client side
Page is not really a sub resource of items, but a sub product of the listing items strategy
In your opinion, which would be the best REST practice approach?
Thanks in advance!
I believe you pointed out what is best practice by doing the research and saying that the first of you options is widely used. It is also the option I believe best conforms to how the query component is meant to be used. In RFC 3986, it states
The query component contains non-hierarchical data that, along with
data in the path component (Section 3.3), serves to identify a
resource
(from Querystring in REST Resource url).
Another way to look at it is that your second option is saying that /items/from-page-50-limited-to-25 is a unity resource/entity as well as is /items/from-page-1-limited-to-25. For me it's more natural to think that /items is it unique resource where I can get a selection of the collection.