Categories
http http-get rest

HTTP GET with request body

2775

I’m developing a new RESTful webservice for our application.

When doing a GET on certain entities, clients can request the contents of the entity.
If they want to add some parameters (for example sorting a list) they can add these parameters in the query string.

Alternatively I want people to be able to specify these parameters in the request body.
HTTP/1.1 does not seem to explicitly forbid this. This will allow them to specify more information, might make it easier to specify complex XML requests.

My questions:

  • Is this a good idea altogether?
  • Will HTTP clients have issues with using request bodies within a GET request?

https://www.rfc-editor.org/rfc/rfc2616

34

  • 592

    The advantage is that allows easily sending XML or JSON request bodies, it doesn’t have a length restriction and it’s easier to encode (UTF-8).

    – Evert

    Jun 10, 2009 at 21:51

  • 37

    If what you’re after is a safe and idempotent method that allows request bodies, you may want to look at SEARCH, PROPFIND and REPORT. Of course not using GET and having a request body defeats caching more or less.

    Dec 6, 2011 at 9:33

  • 285

    @fijiaaron: It’s 3 years later, and since then I’ve gotten extensive experience writing webservices. It’s basically all I have been doing for the last few years. I can safely say, it is indeed a very bad idea to add a body to a GET request. The top two answers stand like a rock.

    – Evert

    Aug 31, 2012 at 0:34

  • 37

    @Ellesedil: Simply put: Whatever advantages that exist to using GET over POST, exist because of how HTTP is designed. Those advantages no longer exist, when you violate the standard in this way. Therefore there’s only one reason left to use GET + a request body instead of POST: Aesthetics. Don’t sacrifice robust design over aesthetics.

    – Evert

    May 1, 2014 at 16:24

  • 20

    To underline what Evert said: “it doesn’t have a length restriction”. If your GET with query parameters is breaking length restriction (of 2048), then what other choice is there other than to put the query string information in a json object, for example, in the body of the request.

    May 17, 2015 at 15:22


2251

+150

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

Yes, you can send a request body with GET but it should not have any meaning. If you give it meaning by parsing it on the server and changing your response based on its contents, then you are ignoring this recommendation in the HTTP/1.1 spec, section 4.3:

…if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.

And the description of the GET method in the HTTP/1.1 spec, section 9.3:

The GET method means retrieve whatever information ([…]) is identified by the Request-URI.

which states that the request-body is not part of the identification of the resource in a GET request, only the request URI.

Update

The RFC2616 referenced as “HTTP/1.1 spec” is now obsolete. In 2014 it was replaced by RFCs 7230-7237. Quote “the message-body SHOULD be ignored when handling the request” has been deleted. It’s now just “Request message framing is independent of method semantics, even if the method doesn’t define any use for a message body” The 2nd quote “The GET method means retrieve whatever information … is identified by the Request-URI” was deleted. – From a comment

From the HTTP 1.1 2014 Spec:

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.

33

  • 101

    Caching / proxying are the two things you’re most likely to break, yes. “Semantics” is just another way of saying “the way people who make other components will expect other components to operate”. If you violate semantics, you’re more likely to see things break in places where people wrote things that expected you to be honoring those semantics.

    Aug 18, 2013 at 1:33


  • 167

    Elasticsearch is a fairly major product that utilises HTTP request bodies in GET. According to their manual whether a HTTP request should support having a body or not is undefined. I’m personally not comfortable with populating a GET request body, but they seem to have a different opinion and they must know what they’re doing. elastic.co/guide/en/elasticsearch/guide/current/…

    – GordonM

    Oct 9, 2015 at 16:22


  • 35

    @iwein giving GET request bodies meaning is in fact not a violation of the spec. HTTP/1.1 specifies that servers SHOULD ignore the body, but RFC 2119 specifies that implementers are allowed to ignore “SHOULD” clauses if they have good reason to do so. Rather, a client does violate the spec if it assumes that changing the GET body will not change the response.

    Dec 10, 2015 at 11:03

  • 138

    The RFC2616 referenced as “HTTP/1.1 spec” is now obsolete. In 2014 it was replaced by RFCs 7230-7237. Quote “the message-body SHOULD be ignored when handling the request” has been deleted. It’s now just “Request message framing is independent of method semantics, even if the method doesn’t define any use for a message body” The 2nd quote “The GET method means retrieve whatever information … is identified by the Request-URI” was deleted. So, I suggest to edit the answer @Jarl

    Nov 4, 2016 at 21:47


  • 43

    I know that it’s an old thread – I stumbled upon it. @Artem Nakonechny is technically right but the new spec says “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.” So it’s still not a really good idea if can be avoided.

    – fastcatch

    Sep 29, 2017 at 13:39

351

While you can do that, insofar as it isn’t explicitly precluded by the HTTP specification, I would suggest avoiding it simply because people don’t expect things to work that way. There are many phases in an HTTP request chain and while they “mostly” conform to the HTTP spec, the only thing you’re assured is that they will behave as traditionally used by web browsers. (I’m thinking of things like transparent proxies, accelerators, A/V toolkits, etc.)

This is the spirit behind the Robustness Principle roughly “be liberal in what you accept, and conservative in what you send”, you don’t want to push the boundaries of a specification without good reason.

However, if you have a good reason, go for it.

10

  • 265

    The Robustness Principle is flawed. If you are liberal in what you accept, you will get crap, if you have any success in terms of adoption, just because you accept crap. That will make it harder for you to evolve your interface. Just look at HTML. That’s the reboustness principle in action.

    Aug 9, 2011 at 1:43

  • 36

    I think the success and breadth of adoption (and abuse) of the protocols speaks to the value of the robustness principle.

    – caskey

    Aug 15, 2011 at 3:46

  • 47

    Have you ever tried parsing real HTML? It’s not feasible to implement it yourself, that’s why almost everyone – including the really big players like Google (Chrome) and Apple (Safari), did not do it but relied on existing implementations (in the end they all relied on KDE’s KHTML). That reuse is of course nice, but have you tried displaying html in a .net application? It’s a nightmare, as you either have to embed an – unmanaged – IE (or similar) component, with its issues and crashes, or you use the available (on codeplex) managed component that doesn’t even allow you to select text.

    Sep 2, 2011 at 14:10

  • 10

    Not only does the HTTP spec allow body data with GET request, but this is also common practice: The popular ElasticSearch engine’s _search API recommends GET requests with the query attached in a JSON body. As a concession to incomplete HTTP client implementations, it also allows POST requests here.

    Oct 25, 2013 at 11:52


  • 8

    @ChristianPietsch, it is common practice today. Four years ago it was not. While the spec explicitly allows a client to optionally include (MAY) an entity in a request (section 7), the meaning of MAY is defined in RFC2119 and a (crappy) proxy server could be spec compliant while stripping off entities in GET requests, specifically as long as it doesn’t crash, it can provide ‘reduced functionality’ by forwarding the request headers and not the included entity. Likewise there are a host of rules about what version changes MUST/MAY/SHOULD be made when proxying among different protocol levels.

    – caskey

    Oct 28, 2013 at 21:49


213

You will likely encounter problems if you ever try to take advantage of caching. Proxies are not going to look in the GET body to see if the parameters have an impact on the response.

4

  • 15

    Using ETag/Last-Modified header fields help in this way: when a “conditional GET” is used, the proxies/caches can act on this information.

    – jldupont

    Jan 15, 2010 at 11:42

  • 4

    @jldupont Caches use the presence of validators to know whether a stale response can be re-validated, however, they are not used as part of the primary or secondary cache key.

    Mar 26, 2014 at 14:42

  • 12

    You could fix that with a checksum of the body in a query parameter

    Jan 3, 2020 at 14:33

  • 1

    For caching just add hash of body to url! 🙂

    – hex

    Feb 11 at 15:51