Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RESTful URL design for search

Tags:

rest

I'm looking for a reasonable way to represent searches as a RESTful URLs.

The setup: I have two models, Cars and Garages, where Cars can be in Garages. So my urls look like:

/car/xxxx   xxx == car id   returns car with given id  /garage/yyy   yyy = garage id   returns garage with given id 

A Car can exist on its own (hence the /car), or it can exist in a garage. What's the right way to represent, say, all the cars in a given garage? Something like:

/garage/yyy/cars     ? 

How about the union of cars in garage yyy and zzz?

What's the right way to represent a search for cars with certain attributes? Say: show me all blue sedans with 4 doors :

/car/search?color=blue&type=sedan&doors=4 

or should it be /cars instead?

The use of "search" seems inappropriate there - what's a better way / term? Should it just be:

/cars/?color=blue&type=sedan&doors=4 

Should the search parameters be part of the PATHINFO or QUERYSTRING?

In short, I'm looking for guidance for cross-model REST url design, and for search.

[Update] I like Justin's answer, but he doesn't cover the multi-field search case:

/cars/color:blue/type:sedan/doors:4 

or something like that. How do we go from

/cars/color/blue 

to the multiple field case?

like image 737
Parand Avatar asked Oct 16 '08 04:10

Parand


People also ask

What is a RESTful URL pattern?

Under REST principles, a URL identifies a resource. The following URL design patterns are considered REST best practices: URLs should include nouns, not verbs. Use plural nouns only for consistency (no singular nouns).

Should a search API be get or post?

GET requests should be used to retrieve data when designing REST APIs; POST requests should be used to create data when designing REST APIs. Creating something is a side effect — if not the point. The HTTP GET method isn't supposed to have side effects. It's considered read-only for retrieving data.


2 Answers

For the searching, use querystrings. This is perfectly RESTful:

/cars?color=blue&type=sedan&doors=4 

An advantage to regular querystrings is that they are standard and widely understood and that they can be generated from form-get.

like image 57
pbreitenbach Avatar answered Sep 19 '22 10:09

pbreitenbach


The RESTful pretty URL design is about displaying a resource based on a structure (directory-like structure, date: articles/2005/5/13, object and it's attributes,..), the slash / indicates hierarchical structure, use the -id instead.

#Hierarchical structure# I would personaly prefer:

/garage-id/cars/car-id /cars/car-id   #for cars not in garages 

If a user removes the /car-id part, it brings the cars preview - intuitive. User exactly knows where in the tree he is, what is he looking at. He knows from the first look, that garages and cars are in relation. /car-id also denotes that it belongs together unlike /car/id.

#Searching# The searchquery is OK as it is, there is only your preference, what should be taken into account. The funny part comes when joining searches (see below).

/cars?color=blue;type=sedan   #most prefered by me /cars;color-blue+doors-4+type-sedan   #looks good when using car-id /cars?color=blue&doors=4&type=sedan   #I don't recommend using &* 

Or basically anything what isn't a slash as explained above.
The formula: /cars[?;]color[=-:]blue[,;+&], * though I wouldn't use the & sign as it is unrecognizable from the text at first glance.

** Did you know that passing JSON object in URI is RESTful? **

Lists of options

/cars?color=black,blue,red;doors=3,5;type=sedan   #most prefered by me /cars?color:black:blue:red;doors:3:5;type:sedan /cars?color(black,blue,red);doors(3,5);type(sedan)   #does not look bad at all /cars?color:(black,blue,red);doors:(3,5);type:sedan   #little difference 

##possible features?## Negate search strings (!)
To search any cars, but not black and red:
?color=!black,!red
color:(!black,!red)

Joined searches
Search red or blue or black cars with 3 doors in garages id 1..20 or 101..103 or 999 but not 5 /garage[id=1-20,101-103,999,!5]/cars[color=red,blue,black;doors=3]
You can then construct more complex search queries. (Look at CSS3 attribute matching for the idea of matching substrings. E.g. searching users containing "bar" user*=bar.)

#Conclusion# Anyway, this might be the most important part for you, because you can do it however you like after all, just keep in mind that RESTful URI represents a structure which is easily understood e.g. directory-like /directory/file, /collection/node/item, dates /articles/{year}/{month}/{day}.. And when you omit any of last segments, you immediately know what you get.

So.., all these characters are allowed unencoded:

  • unreserved: a-zA-Z0-9_.-~
    Typically allowed both encoded and not, both uses are then equivalent.
  • special characters: $-_.+!*'(),
  • reserved: ;/?:@=&
    May be used unencoded for the purpose they represent, otherwise they must be encoded.
  • unsafe: <>"#%{}|^~[]`
    Why unsafe and why should rather be encoded: RFC 1738 see 2.2

Also see RFC 1738#page-20 for more character classes.

RFC 3986 see 2.2
Despite of what I previously said, here is a common distinction of delimeters, meaning that some "are" more important than others.

  • generic delimeters: :/?#[]@
  • sub-delimeters: !$&'()*+,;=

More reading:
Hierarchy: see 2.3, see 1.2.3
url path parameter syntax
CSS3 attribute matching
IBM: RESTful Web services - The basics
Note: RFC 1738 was updated by RFC 3986

like image 35
Qwerty Avatar answered Sep 18 '22 10:09

Qwerty