views:

33

answers:

2

What's the best way to represent a list resource when the list can be "owned" by different resources?

Take your typical blog example.

Say you've got Posts, Comments and Users. A Post has many Comments and a User is the author of many Comments.

You may want to get a list of Comments within the context of a given User (e.g. that User's commenting history), for a given Post (e.g. all the comments on that post) or maybe just all of the Comments, period (though this is not terribly likely).

You could have three different URIs:

/user/user_id/comments
/post/post_id/comments
/comments

Is this OK? My understanding is that URIs should be idempotent. Is it more "RESTful" to have a single url: /comments

and pass filtering parameters? e.g.

/comments?user=user_id
/comments?post=post_id

I guess this second method means you can also filter by user and post with

/comments?user=user_id&post=post_id

But I like how the first example exposes hierarchical context.

What's the best practice here?

A: 

Your first example seems the better of the two to me. Don't forget an even bigger point, which is your service should be navigable through linked data. So if I were to go to /user/123 then I would see a link [href, a] to /user/123/comments that tells me another piece of the service lives at that URI.

Gandalf
+1  A: 

My understanding is that URIs should be idempotent.

URIs are not operations, and thus cannot be described as idempotent. Idempotency simply means that if you make the same operation twice, the final state of the system is the same as if you had made the operation once. HTTP requests on URIs, on the other hand, can be idempotent, but not all of them have to be. HTTP PUT and DELETE, for example, should always be idempotent, but HTTP POST may or may not be. HTTP GET shouldn't substantially change the state of the system at all.

As for friendly URI design (tangential to REST) my recommendation is to use query parameters for things that feel like queries; usually sub-selection of some larger set of resources, e.g. pagination and/or searches. In this case /user/{user_id}/comments is perfectly OK. However, I would advise against exposing database keys in URIs; that's an implementation detail that you should hide in the interests of ensuring that URIs don't change at a later date when you outgrow your current implementation. For things like the user_id value, it's better to use some other unique value like the username there.

Bob Aman