17
votes

I am designing an API and I wonder if it is fine to send a JSON payload on a GET request?

In this other question Payloads of HTTP Request Methods, we can find according to this link:

  • HEAD - No defined body semantics.
  • GET - No defined body semantics.
  • PUT - Body supported.
  • POST - Body supported.
  • DELETE - No defined body semantics.
  • TRACE - Body not supported.
  • OPTIONS - Body supported but no semantics (maybe in the future).

Does this mean that I should not send a GET request with a payload? Are there risks to do so?

  • Like having some HTTP client libraries incapable of sending such a payload?
  • Or my Java API code not being portable on certain application servers?
  • Anything else?

I found out that ElasticSearch was using such a payload on a GET request:

$ curl -XGET 'http://localhost:9200/twitter/tweet/_search?routing=kimchy' -d '{
    "query": {
        "filtered" : {
            "query" : {
                "query_string" : {
                    "query" : "some query string here"
                }
            },
            "filter" : {
                "term" : { "user" : "kimchy" }
            }
        }
    }
}
'

So if this popular libary does it and nobody complains, then perhaps I can do the same?

By the way, I would like to know if this is OK to mix queryString parameters and JSON payload? Exactly like this ElasticSearch query does. If so, are there rules so that we know which arguments should be queryString parameters, or payload parameters?


Here we can read: HTTP GET with request body

Roy Fielding's comment about including a body with a GET request.

Yes. In other words, any HTTP request message is allowed to contain a message body, and thus must parse messages with that in mind. Server semantics for GET, however, are restricted such that a body, if any, has no semantic meaning to the request. The requirements on parsing are separate from the requirements on method semantics.

So, yes, you can send a body with GET, and no, it is never useful to do so.

This is part of the layered design of HTTP/1.1 that will become clear again once the spec is partitioned (work in progress).

....Roy

Then I don't really understand why it is never useful, because it makes sense in my opinion to send complex queries to the server that wouldn't fit well on queryParam or matrixParam. I think ElasticSearch API designers think the same...


I am planning to design an API which can be called like that:

curl -XGET 'http://localhost:9000/documents/inbox?pageIndex=0&pageSize=10&sort=title'

curl -XGET 'http://localhost:9000/documents/trash?pageIndex=0&pageSize=10&sort=title'

curl -XGET 'http://localhost:9000/documents/search?pageIndex=0&pageSize=10&sort=title' -d '{
    "someSearchFilter1":"filterValue1",
    "someSearchFilter2":"filterValue2",
    "someSearchFilterList": ["filterValue3","xxx"]
    ... a lot more ...
}
'

Does it seem fine to you? Based on the above considerations.


4
One risk would be that client libraries wouldn't allow payloads to be sent in a GET request. I didn't even realize you could do this with curl, honestly.bdkosher

4 Answers

3
votes

Having the GET response vary based on the request body will break caching. Don't go there.

3
votes

Also see: HTTP GET with request body - for more detail on this.

The gist is: Yes you can, but you probably shouldn't for various reasons, including:

  • You're likely ignoring HTTP spec recommendations (you probably want to POST)
  • You may introduce caching issues
  • This is not intuitive as far as REST APIs go
2
votes

Google App Engine, a popular web framework, uses a special url fetch library, which does not support making HTTP GET requests with a payload. Accordingly, if you want your API to reach Google App Engine users, then I would not recommend requiring this behavior.

I've opened an issue regarding this with google.

0
votes

Just because you can do something, doesn't mean you should. I'm sorry if this sounds infuriatingly tautological but the thing about standards is that they're standard - and HTTP is one of the most established standards there is. It's not perfect, and there are a lot of things which a lot of people would like to change about it, but the fact that nearly everyone is still using URL parameters for use cases such as this is to me sufficient indication that there aren't any reliable alternatives right now.

The answers from speedplane and Julian Reschke give two concrete examples of things that will break if you rely on GET requests with a body/payload. You can write your app differently to everyone else, if you want, but the web is one area where standards should perhaps be taken even more seriously than normal. I know it's tempting to be a trailblazer, but with all due respect, consider just how many websites exist, and how many web programmers there are building and maintaining them. If there was a definitively better way, you'd most likely see it widely used in production by now.

Standards change/are adopted slowly because so many people have to agree on them for them to work. You're correct in saying that there are applications that break the rules, but you'll notice they've caused headaches for people, and workarounds/redundancy measures are required in certain cases, as mentioned by Aetherus in their comment on another answer. I tend to take the path of least resistance on issues like this. If you really want to do it, I'm sure you can make it work, though.