How to design RESTful search/filtering?design


If you use the request body in a GET request, you're breaking the REST principle, because your GET request won't be able to be cached, because cache system uses only the URL.

And what's worse, your URL can't be bookmarked, because the URL doesn't contains all the information needed to redirect the user to this page

Use URL or Query parameters instead of request body parameters.



In fact, the HTTP RFC 7231 says that:

A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

For more information take a look at here


I'm currently designing and implementing a RESTful API in PHP. However, I have been unsuccessful implementing my initial design.

GET /users # list of users
GET /user/1 # get user with id 1
POST /user # create new user
PUT /user/1 # modify user with id 1
DELETE /user/1 # delete user with id 1

So far pretty standard, right?

My problem is with the first one GET /users. I was considering sending parameters in the request body to filter the list. This is because I want to be able to specify complex filters without getting a super long url, like:

GET /users?parameter1=value1&parameter2=value2&parameter3=value3&parameter4=value4

Instead I wanted to have something like:

GET /users
# Request body:
    "parameter1": "value1",
    "parameter2": "value2",
    "parameter3": "value3",
    "parameter4": "value4"

which is much more readable and gives you great possibilities to set complex filters.

Anyway, file_get_contents('php://input') didn't return the request body for GET requests. I also tried http_get_request_body(), but the shared hosting that I'm using doesn't have pecl_http. Not sure it would have helped anyway.

I found this question and realized that GET probably isn't supposed to have a request body. It was a bit inconclusive, but they advised against it.

So now I'm not sure what to do. How do you design a RESTful search/filterng function?

I suppose I could use POST, but that doesn't seem very RESTful.

HTTP GET with request body

Roy Fielding's comment about including a body with a GET request.

Yes. In other words, any HTTP request message is allowed to contain a message body, and thus must parse messages with that in mind. Server semantics for GET, however, are restricted such that a body, if any, has no semantic meaning to the request. The requirements on parsing are separate from the requirements on method semantics.

So, yes, you can send a body with GET, and no, it is never useful to do so.

This is part of the layered design of HTTP/1.1 that will become clear again once the spec is partitioned (work in progress).


Yes, you can send a request body with GET but it should not have any meaning. If you give it meaning by parsing it on the server and changing your response based on its contents, then you are ignoring this recommendation in the HTTP/1.1 spec, section 4.3:

[...] if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.

And the description of the GET method in the HTTP/1.1 spec, section 9.3:

The GET method means retrieve whatever information ([...]) is identified by the Request-URI.

which states that the request-body is not part of the identification of the resource in a GET request, only the request URI.

You will likely encounter problems if you ever try to take advantage of caching. Proxies are not going to look in the GET body to see if the parameters have an impact on the response.

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:

/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.


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)   #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:

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.)


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_.-~
  • reserved: ;/?:@=&$-_.+!*'(),
  • unsafe*: <>"#%{}|\^~[]`

*Why unsafe and why should rather be encoded: RFC 1738 see 2.2

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

Restful API naming conventions

You are probably aware that REST has no strict rules, you are more or less free to implement it however you like, but here are my 2 cents{orgId}

However this sounds like a good url because it sort of tells you what it does by reading it, this is not a great idea. Normally, each url segment specifies a resource that exists or can exist.

In this case, users represents one or more resources and so does organisation, but by does not, it's probably nothing more than a word to help clarify what the API does.

The call is expected to return "users" and therefore the "resource" (first part of the call) should relate to it.

A resource is not necessarily specified in the first part of the url. It can be the 2nd, 3rd or 10th if you want{orgId}/users

This looks much better but I think there is 1 point of improvement. You should rename organisation to organisations, to match users


then gets the organisation with id orgId, and{orgId}/users

gets all the users that belong to that organisation.

To further narrow it down you could do{orgId}/users/{userId}

to get one specific user belonging to one specific organisation

UPDATE: I am not to worried about what comes after the{resource}. The question relates mostly to whether the HTTP action (GET, POST, PUT, DELETE) should relate to the first resource or whether it should reflect the relationship

To answer your update:

I already mentioned it above; A resource is not necessarily specified in the first part of the url.. If the quality of the url improves by shifting the wanted resource to the back of the url, go ahead and do so

Let me start with this: technically, it shouldn't really matter. REST states that URL's must be discoverable through links, like links in normal (HTML) web pages.

However, a consistent, self-explanatory URL-structure won't harm at all. I'd suggest a hierarchical structure in URLs:

  • /organisations returns a list of all organisations
  • /organisations/123 returns a specific organisation (#123)
  • /organisations/123/users returns a list of users that are associated to that organisation
  • etc.

An alternative would be using a query string for filtering:

  • /users returns a list of all users
  • /users?organisation=123 returns a list of users that are associated to that organisation

From this hierarchical perspective, /users/by/organisation/123 wouldn't make much sense. What would be the result of calling /users/by/organisation? Or /users/by?