Request bodies in GET requests
12 years ago I asked on Stack Overflow: Are HTTP GET requests allowed to have request bodies?. This got a 2626 upvotes and a whopping 1.6 million views, so clearly it’s something lots of people are still curious about, and in some cases disagree with the accepted answer.
Because it keeps popping up in my Stack Overflow notifications (and I compulsively visit the site), the question has lived in my head rent-free. I keep adding context in my head, and I’ve been meaning to write some of this down for a few years now and hopefully evict it.
Anyway, if you’re just looking for a quick answer, it’s ‘No, you shouldn’t do
this.’, you should probably use QUERY
.
Undefined behavior
A number of people (most famously ElasticSearch) have gotten this wrong, but why? I think it’s because of this sentence in the HTTP Spec:
A payload within a GET request message has no defined semantics
That sentence could easily suggest that there’s no specific behavior associated
to request bodies with GET
requests, and that the behavior is left up to the
implementor.
The reality is that this is more like Undefined behavior from languages like C/C++. My understanding is that leaving certain aspects of the C language undefined (instead of for example requiring an error to be thrown) leaves room for compiler implementations to make certain optimizations. Some compilers also have fun with this; GCC hilariously starts a video game in a specific case of undefined behavior which really brings home this point.
If you were to write a C program that relies on how a compiler dealt with specific undefined behavior, it means your program is no longer a portable C program, but it’s written in variant of C that only works on some compilers.
The same applies for HTTP as well. It’s true that undefined behavior means that you as a server developer can define it, but you are not an island!
When working with HTTP, there’s servers but also load balancers, proxies,
browsers and other clients that all need to work together. The behavior isn’t
just undefined server-side, a load balancer might choose to silently drop
bodies or throw errors. There’s many real-world examples of this. fetch()
for example will throw an error.
This hasn’t stopped people from doing this anyway. OpenAPI removed
support for describing GET
request bodies in version 3.0 (and DELETE
,
which has the same issue!), but was quitely added back in 3.1 to not
prevent people from documenting their arguably broken APIs.
Why it’s not defined
The best source I have is this quote from Roy Fielding in 2007. Roy Fielding coined REST is and is one of the main authors of the HTTP/1.1 RFCs.
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
(His message was originally sent to the now-dead rest-discuss group on Yahoo Groups, but I found an archive in JSON format)
However, I always found this answer unsatisfying. I understand that you might want a low-level protocol design that just passes messages containing headers, bodies,
Truncated by Planet PHP, read more at the original (another 9288 bytes)