RESTful URL Design For Search And Collections
I’m trying to find the appropriate design for RESTful design of URLs for search and for collections of items.
The setup: we have two models, Cars and Garages, where Cars can be in Garages. Base URLs:
/car/xxx (xxx = car id)
/garage/yyy (yyy = garage id)
Now we want to provide a search for cars - eg. show me all the blue sedans with 4 doors. What’s the appropriate URL?
1 - /cars/color/blue/type/sedan/doors/4
2 - /cars/color:blue/type:sedan/doors:4
3 - /cars/?color=blue&type=sedan&doors=4
4 - /car/search/...
None of these are satisfying.
1 through 3 use “cars” as the base (as opposed to “car”). So the pattern for doing searches / collections would be to pluralize the model. This seems ok.
1 has arbitrary ordering of the fields and no good way to distinguish fields versus their values. 2 is slightly better, but still doesn’t seem right.
3 uses the QUERYSTRING for the parameters instead of the PATHINFO, and frankly looks better to me, but I’ve heard of objections to using QUERYSTRING. The problem I have with it is it’s not consistent - if I was searching on a single field my URL would probably be: /cars/color/red or something like that. Having the URL drastically change form just because there are more search parameters seems wrong.
4 uses the “car” base url along with the verb “search”. That seems wrong - verbs shouldn’t be part of the URL, right? It’s been suggested several times though.
Now a slightly different case - let’s find all the cars in a given garage:
1 - /garage/yyy/cars
2 - /cars/?garage=yyy
1 seems pretty good in this case.
Please chime in with your thoughts, either in the comments here or in the Stackoverflow thread.
Manage your expenses via Email, SMS, Twitter, Voice (Jott: Call and say your expense), IM (Yahoo, AIM, MSN), or Web.
I like number 1. If you’re sticking to a name/value pair concept, then you have a built-in pattern for distinguishing fields from values. “cars” tells you it’s a search….everything after that is a field followed by a value. The order doesn’t have to matter, if you’re putting them all into one long query internally. If you want it to matter, then you could use it as a chance for optimization, depending on your underlying filter logic.
Example: /cars/color/magenta/type/sedan/doors/4 would first get the cars that are magenta (likely a small number) and have less to filter out when selecting the sedans with four doors.
/cars/type/sedan/doors/4/color/magenta would retrieve a lot of sedans before filtering those with four doors, then finally those that are magenta.
Converting this order to the order in which you do table joins against an underlying database could be interesting.
Number 3 fits naturally with a HTML form on a webpage. A redirect after receiving the submitted form to one of the ‘nicer’ URI might be an interesting thing … - allowing these ‘nicer’ URLs breathing space to change, which I think is a good thing - particularly with regards to not coupling your clients to a particular URI scheme.
(?)
Roger, I ended up using 3 for exactly the reasons you mention. It works well, but I feel somehow RESTless about it…
interesting read, thanx — i did not know, that so many people (besides me) care about “URL design” :). i like the solution provided by justin in the stackoverflow thread very much. but: i still wonder, how you will use such an URL, when you make your selections with a webform and submit this. you would have to rewrite the URL on server-side and perform a second request. would you additionally use javascript to build the URL client-side? someone with javascript enabled browser would not be redirected (and therefore only one request for the user hits the server) in that case?