1

I am trying to understand which should be the correct REST approach to name some of a e-commerce style endpoint.

If I am not mistaken, getting a list of products and the details of one of each will end up with two GET endpoints as

A) GET /products

B) GET /products/id

(I deliberately skipped pagination issues)

If I am looking at the list of shops which sell a specific product I can specify and endpoint as such

C) GET /products/id/shops

I struggle to understand though what happens if I need to specify more than one product for shop reserach.

Can the above endpoint be expanded to take multiple parameters or this is somehow discouraged? In other words, should I be looking into something like

1) GET /products/id1,id2,id3/shops
2) GET /products/id1/shops [id2,id3]

or rather a completely new

3) GET /shops [id1,id2,id3]

?

Notes

  1. Unanswered question in SO seems to underline that this is a sort of an untold story in RESTful services... :)
  2. My current source of reference
  3. As referred in many SO answers, as for example here, the URI does not make the service RESTful.

    I agree with it, so to extend the concept a little my point above is that the implementation of the a service like 1) above may be (and in my case is, for server implementation details) different from easily combining the result given by 3 endpoints in the form of C).

    In a more general sense, the implementation of such a combination could be kept internal.

    Thus, yes the URI does not make the service RESTful but it would be nice to extend the cleaniness and expresiveness of the C) form for multiple ids.

Edit In response to the correct note by Lutz in answer, shops may be trated as resources on their own. What if, I came out with this not so clever example, the subresource does not really exists on its own, as for example the free places for 2 movies in a cinema where

GET /movies/12,14/places

where

GET /places?movies=12,14

is obviously feasible but not that RESTful imho.

Community
  • 1
  • 1
Mauro
  • 2,032
  • 3
  • 25
  • 47
  • Getting the details of a list of products does not necessarily require multiple requests. There is no URI-design related reason why the response payload of `GET /products` can't include all the details of each product as well. There might be performance or other issues with that, which would only be known to those familiar with the product you are creating, but that's a design decision for your team, not a constraint of REST. – Scott Offen Feb 06 '15 at 18:21

2 Answers2

2

I would make shops a separate resource.

  • GET /shops lists all shops
  • GET /shops/123 gets the details of shop 123
  • GET /shops?sellsProduct=id1,id2,id3 lists all shop that sell the products

In URLs like /products/id/shops the shops are a subresource of a product. But since a shop can exist independently of any product, this makes not much sense.

  • May I kindly ask you to elaborate in consideration that the subresource may not exist. If we want to think of a real example what if I substitute products with movies (offered in a cinema) and shop with availability. Thus following example 1 above GET/movies/12,14/availability will give me the joint availability of places for the 2 movies. The result will be the same as for the /availability?movies=12,14 but in this case it can questioned if an availability exists independently of a movie. – Mauro Feb 06 '15 at 12:56
  • Hope it's not too convoluted :) – Mauro Feb 06 '15 at 12:56
2

I agree with the answer given by Lutz Horn. Furthermore, I'm not sure why you would think that using the query string in a GET request is "not that RESTful".

To quote from O'Reilly's RESTful Web Services, pg 233, under the header URI Design (emphasis mine):

Use punctuation characters to separate multiple pieces of data at the same level of hierarchy. Use commas when the order of the items matters, as it does in latitude and longitude: /Earth/37.0,-95.2. Use semicolons when the order doesn't matter: /color-blends/red;blue.

Use query variables only to suggest arguments being plugged into an algorithm, or when the other two techniques fail. If two URIs differ only in their query variables, it implies that they're the different sets of inputs into the same underlying algorithm.

This should give you sufficient direction in determining how to construct your routes. While you could easily construct it thusly (using semicolons, because it doesn't seem that order matters here):

GET /products/id1;id2;id3/shops

You could just as easily write it this way:

GET /shops?productIds=id1,id2,id3

And this might be a more reasonable approach given that what you indicate you are doing is searching for all shops that carry a particular item, and search is an algorithm for which product ids are input parameters.

To your example of movies (if I am understanding it correctly), if you are looking for places (our resource) where the movie (or movies) is showing AND seating is available:

GET /places?movie=id1,id2,id3&availability=true

It looks like you just have additional search parameters. If I am misunderstanding your "subresource may not exist" comment, please clarify this for us so that we can address it properly.

Scott Offen
  • 6,933
  • 3
  • 21
  • 24
  • 1
    Hi Scott, I completely missed the example you cite. Shame on me. You are right in saying that order does not matter, thus semi column seem the way to go. – Mauro Feb 06 '15 at 18:43
  • On the "not that restful" piece, what I meant is if it is reasonable to have a specific endpoint like /places if the endpoint has got no sense without a context. Citing the same book (on mobile sorry for not pointing the page) the author stress the point that one of the aim is to make the service "discoverable", thus making your suggested solution with semi columns much more elegant. Anyway, thank you for the good answer and for quoting the book. – Mauro Feb 06 '15 at 18:51
  • If you want me to give additional details on the last point, I am more than happy to discuss further! – Mauro Feb 06 '15 at 18:56
  • Ehm... apparently we were talking about two different books. No shame on me then! :) – Mauro Feb 09 '15 at 16:11
  • That would appear to be the case. Made my book mention link to the product page. – Scott Offen Feb 09 '15 at 23:17