How do you search with REST

The question is pretty much in title. I'm developing a REST API, it has a search endpoint with 10 optional parameters. How do I pass them and stay RESTFul?

To ease the question a bit let's agree that:

  • all parameters are AND parameters, user can't make combos, ORs, etc. User can only provide values
  • all values are integers so I don't have to think about URL limits
  • all values are atomic
  • all conditions are about equivalency

Some options I know of:

1. URL parameters.

GET /search?param1=value1&param2=value2...

Quick and easy but I'm not sure it's really RESTFul

2. POST body

POST /search
{
   "param1": "value1",
   "param2": "value2"
}

Looks like a lot of overhead?

 

Any other ideas?

Answers

About RESTfull...

/search isn't really RESTfull, REST works on Resources (e.g. /persons or /orders)

To query Resources you use GET (with parameters)

But this is all very 'religious'. To use POST for a complex query is IMO defendable, but then I would do that on a Resource.

You should have a look at the OData (Oasis) specification: https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=odata
 

I found this, quite close to your question.

POST/PUT, means that you create/update some data. 

I would use a query parameters, in such case.

I agree that query, in general, doesn't fit into the pure REST architecture, and that POST/PUT should be used to create or update resources. I worked in a standards organization for many years and we had many "religious wars" regarding query and REST. There was never any clear answer. What we decided was to use GET with query parameters whenever possible, and when you needed a message body (for example to integrate with SOAP architecture), use POST.

The only truly REST way to handle query is to POST/PUT a query to make it a resource, then use GET to execute the query, then use DELETE to get rid of the query. But this is an awkward way to solve the problem, simply to stay truer to the spirit of a REST architecture.

Would something like that ever make sense if the queries were repeated a lot, across a lot of different applications?  (minus the deleting the query part)

I'd never actually thought of this before.  Have you ever implemented anything like that?  Actually now that I think about it more, it would make more sense to just post the query and have it run (and store if it's not there), rather than getting trying to GET the query first, getting back a 404 or something, and then POSTing it before getting it.

Yes! Storing queries that are re-used a lot is a great use of REST. I haven't implemented anything recently so no code to share with you but the client interface would be like any other REST resource. You could even POST a query that had one or more parameters that could be set when GETting the resource, so your query resource would be more extensible. For example, the resource might always query the same field name in a table, but you might pass a query string in the GET that would define what you were searching for in that field. But then you're on a slippery slope to not being RESTful anymore...

Like others have said, a /search endpoint is inherently non-RESTful.  Are you certain that /search endpoint shouldn't be something else? 

For example, if the search is searching people, then perhaps redesign it as a /person endpoint instead?  If that's the case, then a GET request to /person with URL parameters is definitely the most "RESTful" thing you can do; you're asking for ("GETing") information for a bunch of person resources.

If /search is really what you want, then it's not really following the RESTful architecture anyway, because you aren't asking for information about resources, you're really just asking the server to take an action for you and send you the result.  In this case, you might as well forget about RESTful conventions and just do whatever is most convenient and maintainable. 

I suspect that the user is filling out some sort of a form in the UI with these search parameters.  If that's the case, you might be able to simply POST the object that the form generates to the server, and then pull the parameters out of the request body in your server-side handler method.  In general, whether you're pulling the parameters out of %request.Data or out of  %request.Content, there isn't much code that needs to be written on the server.  So pick the option that makes the client code the most straightforward.

Comments