16

I have two resources: users and links.

Users can have several links associated with them. I have designed my RESTful API so that you can reach the links associated with a user at the following URI:

/users/:id/links

However, I always need to have a URI for just links – sometimes I might want all links, regardless of user.

For this I have:

/links

Does this sound okay? Having two URIs for links?

I wonder if I should instead reach the links for a user with a URI such as:

/links/user/:id or /links/?user=:id

This way, I only have one resource for links.

  • 3
    hmm.. This one seems more elegant: /links/user/:id – theMarceloR Feb 18 '13 at 20:16
  • 7
    @theMarceloR: That's the only example out of the three that I don't find particularly clear. Is the resource for a link or a user? The URI is far less ambiguous using either the nested resource method (/users/:id/links) or the query string method (/links/?user=:id) since it is in fact a query. /links/user/:id might look nice and/or be easier to route in some frameworks but it is actually quite confusing. – Aaronaught Feb 19 '13 at 0:06
16

No, there is nothing wrong with having multiple resources for the same "thing", in this case lists of links.

We were recently struggling with the same problem. Our decision was to have all resources where there is not a strict ownership not to be nested. In other words, the links would be modeled under

/links -- all links
/links/:linkid -- a particular link

Then, filters on the links collection are expressed as query parameters. So to get the links of a certain user, you would use:

/links?user=/users/:userid

This also allows for easier composition of filters:

/links?user=/users/10&since=2013-01-01

And it is easy to understand conceptually - you have a collection of items, and you add filters to it.

That being said, there is nothing more "RESTful" about this approach than any other URI naming scheme. It's just a convention we found human-readable and easy for us developers to understand and embrace. REST doesn't care about what you put in your resource identifiers.

  • 1
    "All resources where there is not a strict ownership not to be nested" sounds like a good rule to have. Thanks a bunch. – Oliver Joseph Ash Feb 18 '13 at 21:29
  • 5
    I'd say that there is something wrong with having multiple resources for the same physical entity, but that's not actually what this is. Each individual link has a canonical URL (links/:id), whereas each of the resources above are in fact a single resource (/links) with filters applied. Also, I'm weirded out by the ?user=users/:userid in the query string; what is wrong with just ?userid=:userid? – Aaronaught Feb 19 '13 at 0:03
  • 2
    @Aaronaught: the reason to stick to uri's instead of bare ids is so that clients can treat all resource identifiers equally, that is a client need only know that 'this user is identified by "/*******"; where the *'s are opaque. but that same identifier can always be used to refer to that resource (as in, with links), to fetch the most current version of that resource, and so on. the content of that uri is only understood by the origin server. This also means that if the identifiers need to change, say /realm/:businessid/users/:id, the client doens't change at all. – SingleNegationElimination Oct 19 '13 at 18:26
  • @TokenMacGuy: Sorry, I don't understand any part of your comment. What's the practical difference between /users/:userid/links and /links?userid=:userid? In both cases the identifiers don't change, they fetch the current version of that resource, and the client treats them the same way. There's no such thing as a canonical URL for this because it's not a resource, it's a query, so these are just two different types of query syntax. I'm also not clear on how the client wouldn't need to change if the URL structure changes; that's considered a breaking change in REST unless a 301 is in place. – Aaronaught Oct 19 '13 at 19:52
  • 1
    @Aaronaught: I might have misunderstood your concern. Supposing /links supports a query interface, /links?user=/users/123 permits a black-box approach to resource identifiers in clients that /links?userid=123 does not. the latter requires the client understand what a userid is and how to get it, presumably out of the resource it obtained from /users/123 or /links/456/user. The former means the client can use the uri unmodified; supposing the /links/.../user gives a hypermedia response (say, with Location: headers). – SingleNegationElimination Oct 19 '13 at 22:00
1

So my concern is: /users/:userid/links returns "links", BUT if the user_id is not identified, this should return a 404.

However

/links?userid=:userid would potentially return an empty list (essentially a 200) which is actually probably a bug. And quite possible.

Although both work, the nesting gives you additional functionality you can later draw on.

protected by gnat Nov 23 '17 at 12:08

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.