Design RESTful query API with a long list of query parameters

missionE46 picture missionE46 · Jan 7, 2013 · Viewed 85.2k times · Source

I need to design a RESTful query API, that returns a set of objects based on a few filters. The usual HTTP method for this is GET. The only problem is, it can have at least a dozen filters, and if we pass all of them as query parameters, the URL can get quite long (long enough to be blocked by some firewall).

Reducing the numbers of parameters is not an option.

One alternative I could think of is to make use of the POST method on the URI and send the filters as part of the POST body. Is this against being RESTfull (Making a POST call to query data).

Anyone have any better design suggestions?

Answer

Amir Abiri picture Amir Abiri · Aug 13, 2015

Remember that with a REST API, it's all a question of your point of view.

The two key concepts in a REST API are the endpoints and the resources (entities). Loosely put, an endpoint either returns resources via GET or accepts resources via POST and PUT and so on (or a combination of the above).

It is accepted that with POST, the data you send may or may not result in the creation of a new resource and its associated endpoint(s), which will most likely not "live" under the POSTed url. In other words when you POST you send data somewhere for handling. The POST endpoint is not where the resource might normally be found.

Quoting from RFC 2616 (with irrelevant parts omitted, and relevant parts highlighted):

9.5 POST

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. POST is designed to allow a uniform method to cover the following functions:

  • ...
  • Providing a block of data, such as the result of submitting a form, to a data-handling process;
  • ...

...

The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result.

If a resource has been created on the origin server, the response SHOULD be 201 (Created)...

We have grown used to endpoints and resources representing 'things' or 'data', be it a user, a message, a book - whatever the problem domain dictates. However, an endpoint can also expose a different resource - for example search results.

Consider the following example:

GET    /books?author=AUTHOR
POST   /books
PUT    /books/ID
DELETE /books/ID

This is a typical REST CRUD. However what if we added:

POST /books/search

    {
        "keywords": "...",
        "yearRange": {"from": 1945, "to": 2003},
        "genre": "..."
    }

There is nothing un-RESTful about this endpoint. It accepts data (entity) in the form of the request body. That data is the Search Criteria - a DTO like any other. This endpoint produces a resource (entity) in response to the request: Search Results. The search results resource is a temporary one, served immediately to the client, without a redirect, and without being exposed from some other canonical url.

It's still REST, except the entities aren't books - the request entity is book search criteria, and the response entity is book search results.