71

Following REST principles, I would want to create a GET method for my API that make a search using some criteria and return the results to the client. The problem is that the criteria can have up to 14 parameters, one of them is a list of complex objects, so...

  • I don't even know if it possible to encode/decode these complex objects to/from url parameters.

  • I didn't calculate how long the url could get but I'm sure it will be large enough and maybe reach the url length limit?

Also, the search should show the results in "real time", I mean, every time the user changes something from the search form he should be able to see the new results without pressing any "search" button.

Could you clarify me these points and what would be your advice to create a restful search method with a lot of parameters?

update: now that I have more experience, I've realized that having to do a search function with A LOT of parameters for a web app is actually something that designates bad design and bad requirements, and @Neil answer has the point. So my advice is do what you can within the scope. Nevertheless, the @Laiv answer is still good for less extreme cases, so take it into account too.

anat0lius
  • 1,039

3 Answers3

78

Before you read my answer, I would like to say that I agreed with @Neil. We have to pick our battles. We usually want to do our best, but sometimes there's too little room for discussion and we have to make decisions against our will.

Anyways, in Neil's answer, I miss one more thing. Documentation. Just to ensure that developers know that POST requests to /search are safe.

That said.

1. Give GET a chance

Consider the GET option first. Check out this question URL's max length. Evaluate whether your longest query string is longer than 2000 characters. If it doesn't, and you don't expect it to be, go with GET. It might seem ugly but it has all the advantages derived from the method' semantics (idempotence, safe and caching). And bookmarking.

1.1 Try encoding the query string

For example, in base 64. Even javascript supports base 64 encodings.

This's how it works:

  1. Build the JSON with all the filters and normalise it.
  2. Parse it to string
  3. Encode it
  4. Send the encoded JSON as request param (/search?q=SGVsbG8gV29ybGQh....).
  5. On the server-side, decode q.
  6. Deserialize the JSON string

Previously, make the longest possible JSON string, encode it and take the length. Evaluate if the encoded string fits in the URL. I have implemented the following snippet on Fiddle.js for you to test. (I hope it still works)1

Base 64 encodes are deterministic and reversible, so there's no chance for collisions.

With encoded queries, we could also save searches in the DB, bookmark the URL too, share links, etc. And, of course, we don't have to escape/unescape the string (something I dislike).

1.2 Try with aliases

Reading this blog about how to design REST APIs, I remembered one more alternative. Aliases for common queries.

I find these to be interesting for the next reasons

  • Shorten the query string length. It makes the API cleaner and user-friendly

    GET /tickets/?status=closed&closedAt=xxx vs GET /tickets/recently-closed/

  • Combinable with more aliases or more request parameters.

    GET /tickets/?status=closed&closedAt=xxx&within=30min vs GET /tickets/recently-closed/?within=30min

  • We can combine aliases with encoded query strings

    GET /tickets/?status=closed&closedAt=xxx&within=30min vs GET /tickets/recently-closed/?q=SGVsbG8g...


1: I have used JSON, but we could use other formats as soon as we can deserialize these on the server-side.

Laiv
  • 14,990
23

If all you have is a hammer, everything looks like a nail. It seems the problem here is that you're trying to turn a search page into a RESTful one, and this hardly seems to be a common pattern for RESTful design to solve.

Simply go with a POST request with parameters as provided by the user in order to get the information you require from the backend. I assume you need not do anything other than perform a search, so there's no chance you'll need to insert through this page. Just add a /search to the end of your URL so you don't risk to run into conflicts with your /users page which would be RESTful.

Neil
  • 22,848
-1

It fully depend on what is your API model: As none or as verb.

If the API is a none then you may want to get list of objects as follow:

GET: /api/v1/objects

In this case you have to send data as request parameters. So you have to describe your parameters as a flat list of key-values:

GET: /api/v1/objects

key1 : val1
key2.key1 : val 21
key2.key2 : val 22
....

Some platforms supports custom parameter resolver (e.g. Spring MVC), an you can convert params into an object.