How to design RESTful search/filtering?

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.


The best way to implement a RESTful search is to consider the search itself to be a resource. Then you can use the POST verb because you are creating a search. You do not have to literally create something in a database in order to use a POST.

For example:

Accept: application/json
Content-Type: application/json
POST http://example.com/people/searches
{
  "terms": {
    "ssn": "123456789"
  },
  "order": { ... },
  ...
}

You are creating a search from the user's standpoint. The implementation details of this are irrelevant. Some RESTful APIs may not even need persistence. That is an implementation detail.


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.

eg:

/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


It seems that resource filtering/searching can be implemented in a RESTful way. The idea is to introduce a new endpoint called /filters/ or /api/filters/ .

Using this endpoint filter can be considered as a resource and hence created via POST method. This way - of course - body can be used to carry all the parameters as well as complex search/filter structures can be created.

After creating such filter there are two possibilities to get the search/filter result.

  • A new resource with unique ID will be returned along with 201 Created status code. Then using this ID a GET request can be made to /api/users/ like:

    GET /api/users/?filterId=1234-abcd
    
  • After new filter is created via POST it won't reply with 201 Created but at once with 303 SeeOther along with Location header pointing to /api/users/?filterId=1234-abcd . This redirect will be automatically handled via underlying library.

  • In both scenarios two requests need to be made to get the filtered results - this may be considered as a drawback, especially for mobile applications. For mobile applications I'd use single POST call to /api/users/filter/ .

    How to keep created filters?

    They can be stored in DB and used later on. They can also be stored in some temporary storage eg redis and have some TTL after which they will expire and will be removed.

    What are the advantages of this idea?

    Filters, filtered results are cacheable and can be even bookmarked.

    链接地址: http://www.djcxy.com/p/7046.html

    上一篇: 查询字符串参数的Java URL编码

    下一篇: 如何设计RESTful搜索/过滤?