Clarifying My Mistake about GET Requests with Body

Posted on Apr 13, 2015

Just the same week after I wrote the post Thoughts about current APIs implementations, I had a discussion, with one of my colleagues, about if sending a body in a GET Request fulfills with the current HTTP/1.1 Standard, which it’s something that I commented on that post and I mentioned that it was the way to make requests with quite few parameters rather than use POST and not having a very large and ugly URL.

After that conversation, he made me see my mistake showing me that doing that it’s no appropriated; here you can read why not and the possible solutions which fulfill the standard.

Clarifying the Current HTTP/1.1 Standard

My colleague brought on the table a response sent by Roy T. Fielding, one of the principal authors of HTTP specification RFC2616 appeared in June 1999 which has been superseded by multiples RFCs 7230, 7231, 7232, 7233, 7234, 7235, 7236 and 7237.

The response says

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 my interpretations about “GET request message has no defined semantics” which I extracted from the paragraph

A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

which you can find in 7231#4.3.1 was wrong.

As I mentioned, it’s not wrong to send a payload (a.k.a body) in a GET request, however because it doesn’t have semantics, means that the doing two or more requests with the same URI with different payload should return the same response, due that it’ll be ignored, hence body will never change what is requested.

What are the possibilities

If we stick to the standard there are basically two solutions

  1. All the parameters are in the URL, considering part of the path and query parameters.
  2. Use a POST request with the parameters, then the server must create a response which store in somehow a response back with a URI to access to it, allowing the client to make a GET request with that URI to retrieve the generated response, refer to this Stack Overflow response for more details.

As I also mentioned in my previous post, if we add all the parameters in the URI then we get ugly URLs and perhaps, they aren’t ideal, but in the case of REST APIs is something that doesn’t matter due machines deal with them besides, obviously, we don’t need to consider web crawlers, so they may only annoy us in our logs.

The second solutions, from my point of view, it’s awkward and I’d only use as exception, when the amount of parameters generate a large URI which may be rejected, even though the current URI standard, RFC 3986 and the URI standard, RFC 3986 don’t have any length limitation, they’ve found, in the real world, some limitations and the recommendations for senders and recipients is to support at least 8000 bytes which are quite a few to generate a large URI.

To see a very good clarification of it, considering real world URI’s length limitations, read this another Stack Overflow response.

Conclusion

The standard isn’t quite clear and doesn’t ban to send payload even though it means nothing.

The URIs are not that short that we can think and the web browsers have, so using GET with a long URLs should almost solve all the use cases, for those that fall outside the solution is the awkward two step request POST and GET, but if you want to stick to the standard don’t use POST as single GET.

I hope that you’ve got to be clearer about this topic when you decide/have/must design an REST API, as I’ve got.

Have a nice week!