4

REST architecture says that a resources state also should get a URL.

I am making a small application with very large queries. I would like to generate URLs with each query, but the queries are often larger than the URL character limit. I tried using URL shorteners but my URLss are too big even for them.

A lot of people online are suggesting using POST, but that is not idempotent. I really do not want to limit my query length and URLs should be able to identify an infinite amount of resources.

Is there a RESTful way to get around having very large URLs that does not involve POST requests?

Qasim Ahmed
  • 177
  • 1
  • 10
  • Use `PUT`, which is at least idempotent. Alas, [every abstraction is leaky](http://www.joelonsoftware.com/articles/LeakyAbstractions.html). – Matt Ball Jun 10 '15 at 21:34
  • ElasticSearch gets around a problem like this by actually including a body in a GET request. Not sure how standard that is (and some HTTP clients won't make such a request), but i haven't seen where the RFCs forbid it. – cHao Jun 10 '15 at 21:36
  • I will look into both your suggestions tomorrow. Interestingly enough someone at the office just told me searching doesn't fit too well with the REST architecture altogether. This makes sense, can any of you agree/disagree? I am very new to REST, have just read the O'Reilly book and I am trying to stick really close to it, even if un-practice, for practice. – Qasim Ahmed Jun 10 '15 at 21:59
  • I disagree. Searching *can* be modeled on REST if you consider queries to be resources. Please take a lookt at my answer. –  Jun 11 '15 at 07:03
  • Searching and REST get along as long as your queries are relatively short and simple -- or if you'll be rerunning long or complicated queries enough to justify persisting them on the server. (Note, the _queries_ are what matter, not the list of results. Short queries can produce lots of results.) Unless there's actually an advantage to persisting the search on the server, making searches a resource is a hack to make you feel better about using the right verb. In return, now you have another resource to manage, and clients aren't going to be particularly inclined to do that management. – cHao Jun 11 '15 at 08:41
  • @cHao About GET bodies, check out [this answer](https://stackoverflow.com/a/983458/616815) with references to the HTTP/1.1 spec. In short: yes, they are permitted, but they cannot make a difference on the response. On the other hand, this is the real world where you do what you have to. – Ken Wayne VanderLinde Jun 10 '17 at 21:21

2 Answers2

3

To model this in a RESFtul way consider queries to be resources. They can be created, retrieved, and eventually deleted.

The client makes a POST request to a queries resource with the query details in the request body.

POST /queries
Content-Type: application/json

{
  "condition1":
  {
    "on": "field1",
    "comparison": "equals",
    "value": 42
  },
  "condition2":
  {
    "on": "field2",
    "comparison": "like",
    "value": "foo%"
  }
}

This creates a new query resource. The server will respond:

201 Created
Location: /queries/D560EC80-1006-11E5-80F6-75919330F945

The path segment D560EC80-1006-11E5-80F6-75919330F945 will be an ID generated by the server for this specific query.

Then the client requests the state of this query resource.

GET /queries/D560EC80-1006-11E5-80F6-75919330F945

The server responds with the query result.

200 OK
Content-Type: application/json

{
  "id": "D560EC80-1006-11E5-80F6-75919330F945",
  "querydetails":
  {
    "condition1":
    {
      "on": "field1",
      "comparison": "equals",
      "value": 42
    },
    "condition2":
    {
      "on": "field2",
      "comparison": "like",
      "value": "foo%"
    }
  },
  "result":
  {
    "length": 12,
    "results":
    [
      {
        // details about the first hit
      },
      // more hits
    ]
  }
}

Later, the client can delete the query.

DELETE /queries/D560EC80-1006-11E5-80F6-75919330F945

Or the sever can automatically delete the query after some time.

  • Abstraction of your query using JSON could be a simpler way as explained in this answer. Another way could be to design your own query shortner but have to implement it on both client and server side. – kingAm Jun 11 '15 at 08:20
  • @kingAm I don't understand. The JSON in my answer ist just for illustration. It is not important. The important part in my answer is to use `POST` to create and `GET` to get the result of a query. –  Jun 11 '15 at 08:24
  • What i meant, instead of putting entire query in URL, you are using JSON to shorten it and put it into POST request body. Which we can consider as standard way of shortening URL. isn't it? Sorry if i am not making any sense. May be i am seeing this questionin wrong context. – kingAm Jun 11 '15 at 09:23
  • 1
    You are correct, I put the details of the query in the body of the POST request, not in the URL of a GET request. This is possible because I consider a query to be a resource. REST is about resources, it is not RPC. –  Jun 11 '15 at 09:24
  • Brilliant, now I understand perfectly. As a side question, POST is neither safe, nor idempotent. If we query using POST is that not considered bad practice.(Although I see in this case why we need to do so) – Qasim Ahmed Jun 11 '15 at 14:07
  • POST is not safe and not idempotent. But that is no problem with this approach. For every POST request to `/queries`, a *new* query resource will be created. The client is only allowed to GET and maybe delete it. As an optimization, the server could return the `Location` of an existing resource if an identical request was POSTed a second time. –  Jun 11 '15 at 14:17
  • @user1907906 REST should be stateless. *Each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server.Session state is therefore kept entirely on the client.* But with the approach in this answer, it is obvious that `POST` and `GET` are correlated and server must keep the result of previous POST for the next GET. I am not saying this is not a practical approach. Just not strictly RESTful. – smwikipedia Dec 20 '15 at 00:38
  • @smwikipedia This is one of the biggest misconceptions of RESTful APIs. REST does not prevent changing information on the server - that would be quite limited! Instead, the basic semantics of a request type ought to be consistent across time and regardless of the API. I.e., GET requests *always* ask to retrieve the resource identified by a URL. And POST requests *always* ask to define a new resource based on the body of the request. The new resource will have its own URL and clients can therefore access it via GET. REST is about modelling resources, not about whether the server is stateless. – Ken Wayne VanderLinde Jun 10 '17 at 09:03
1

Lutz Horn have answered it really well. But there is a good possibility that client might not be wishing to make three api calls - one to create a query response, second to get it, third to delete it.

If you are sure that your query length would remain less than 8 KB(which is the limit for get query length for most webservers), go ahead with GET request. Besides, if you are not interested in caching, use post there is nothing wrong with ignoring REST once in a while if you are well aware of the consequences.

hspandher
  • 13,259
  • 1
  • 23
  • 41
  • "there is nothing wrong with ignoring REST once in a while if you are well aware of the consequences." But don't call the result RESTful. –  Jun 11 '15 at 08:37
  • 1
    I completely agree with you, I wish that argument was sufficient to convince clients to use it in the rest fashion. But It sometimes becomes really difficult to convince clients ,say, to make three http request where one would suffice in non-rest scenario. I myself have had a lot of arguments with clients trying to avoid to do something that is not "restfull", but most of the times you have to give a strong argument in your support. – hspandher Jun 11 '15 at 09:00