How to design RESTful search/filtering?



Answers

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.

e.g.:

/myapp?var1=xxxx&var2=xxxx
/myapp;var1=xxxx/resource;var2=xxxx 

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

Question

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.




I think you should go with request parameters but only as long as there isn't an appropriate HTTP header to accomplish what you want to do. The HTTP specification does not explicitly say, that GET can not have a body. However this paper states:

By convention, when GET method is used, all information required to identify the resource is encoded in the URI. There is no convention in HTTP/1.1 for a safe interaction (e.g., retrieval) where the client supplies data to the server in an HTTP entity body rather than in the query part of a URI. This means that for safe operations, URIs may be long.




As I'm using a laravel/php backend I tend to go with something like this:

/resource?filters[status_id]=1&filters[city]=Sydney&page=2&include=relatedResource

PHP automatically turns [] params into an array, so in this example I'll end up with a $filter variable that holds an array/object of filters, along with a page and any related resources I want eager loaded.

If you use another language, this might still be a good convention and you can create a parser to convert [] to an array.




Links