38

Some HTTP methods, such as POST, require a body to be sent after the headers and the double CRLF.

Others, such as GET, do not have a body, and for them the double CRLF marks the end of the request.

But what about others: PUT, DELETE, ... how to know which one requires a body?

How should a generic HTTP client react to an unknown HTTP method? Reject it? Require a body by default, or not require a body by default?

A pointer to the relevant spec would be appreciated.


Edit : I'll detail a bit more my question, as asked in the comments.

I'm designing a generic HTTP client that a programmer can use to send arbitrary HTTP requests to any server.

The client could be used like this (pseudo-code):

HttpClient.request(method, url [, data]);

The data is optional, and can be raw data (string), or an associative array of key/value pairs.

The library would url-encode the data if it's an array, then either append the data to the URL for a GET request, or send it in the message body for a POST request.

I'm therefore trying to determine whether this HttpClient must/should/must not/should not include a message-body in the request, given the HTTP method chosen by the developer.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
  • generic http client -> generic http server. – Shawn Balestracci May 02 '13 at 13:40
  • @ShawnBalestracci : **?** – BenMorel May 02 '13 at 13:46
  • Please explain what you are trying to do. Why do you want to know which methods require a body? Do you want to write an HTTP server? Have you done [any research](http://stackoverflow.com/questions/299628/is-an-entity-body-allowed-for-an-http-delete-request)? Also the client performs a request and thus determines the method to use; so a client cannot issue a method it does not know. Do you mean the server? I also don't get why you're curious about when to send a body. You send a body when you know you want to, so if you don't know whether you want to, you probably shouldn't. – CodeCaster May 02 '13 at 13:49
  • 1
    A body is *allowed* for `GET` - it just must not change the behaviour of the `GET` request (so, bonus points if you can think of an actual valid use for this) – Damien_The_Unbeliever May 02 '13 at 14:11
  • @CodeCaster I *don't know* what the method is, this is a generic client I'm designing. Please see my updated question. – BenMorel May 02 '13 at 14:47
  • @Damien_The_Unbeliever How does the server know where the request ends then? I thought it knew from the method as well, whether there was a body or not? – BenMorel May 02 '13 at 14:48
  • See (current) bullet point 2 in @Jordan's answer: "the presence of a message-body is signaled by the inclusion of a Content-Length or Transfer-Encoding header" – Damien_The_Unbeliever May 02 '13 at 14:52
  • It's good to realize that there are a lot of HTTP methods. A lot of them come from WEBDAV. http://annevankesteren.nl/2007/10/http-methods - and that's 2007, so there may be even more now. I'd personally put my focus at first on getting HTTTP 1.1 RFC right, and be liberal in other cases. – Myrne Stol May 02 '13 at 16:03
  • You could decide to be more strict than the HTTP spec itself. Apply common sense. You'll get complaints soon enough if it turns out to be a problem for anyone. And before that, you may be doing some good by preventing some unintended or pointless requests being sent. – Myrne Stol May 02 '13 at 16:05
  • @Damien_The_Unbeliever that's exactly it! Good news there's a hard-and-fast rule for determining this. My mistake was to assume it was the method which was responsible for determining it, and not these headers as we now know. – BenMorel May 02 '13 at 16:19
  • @MerynStol Thanks for your comments. I'll be able to apply common sense now that I get a broader picture! – BenMorel May 02 '13 at 16:20
  • @Benjamin Yes, good strategy. Common sense is not that common after all, in this context. I wouldn't have guessed before Googling that there are so much HTTP methods! – Myrne Stol May 02 '13 at 16:27
  • @Benjamin Do you not have usecase where browsers (client) too can send such requests? or would it be just your implementation of generic client? I don't think all webDAV methods are supported by browsers. – harsh May 03 '13 at 05:42
  • @harsh No I don't (yet), but it looks like most browsers [already support request methods beyond GET/POST via XMLHttpRequest](http://stackoverflow.com/questions/165779/are-the-put-delete-head-etc-methods-available-in-most-web-browsers). Furthermore, a developer might very well design an HTTP service for another client than a web browser, and in this case he would need a very generic implementation to connect to it! – BenMorel May 03 '13 at 10:20
  • @Benjamin I had this exact question/problem and realized that URI parameters (?query=whatever) should **not** be conflated with message body in your HTTP client interface. They should be treated separately. – jchook Nov 01 '16 at 13:53

5 Answers5

19

EDIT: compiled list:

  • an entity-body is only present when a message-body is present (section 7.2)
  • the presence of a message-body is signaled by the inclusion of a Content-Length or Transfer-Encoding header (section 4.3)
  • a message-body must not be included when the specification of the request method does not allow sending an entity-body (section 4.3)
  • an entity-body is explicitly forbidden in TRACE requests only, all other request types are unrestricted (section 9, and 9.8 specifically)

For responses, this has been defined:

  • whether a message-body is included depends on both request method and response status (section 4.3)
  • a message-body is explicitly forbidden in responses to HEAD requests (section 9, and 9.4 specifically)
  • a message-body is explicitly forbidden in 1xx (informational), 204 (no content), and 304 (not modified) responses (section 4.3)
  • all other responses include a message-body, though it may be of zero length (section 4.3)

This (RFC 7231) Or This version (From IETF & More In-Depth) is what you want. According to the RFC:

For PUT:

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return a 501 (Not Implemented) response in such cases.

And for DELETE:

The DELETE method requests that the origin server delete the resource identified by the Request-URI. This method MAY be overridden by human intervention (or other means) on the origin server. The client cannot be guaranteed that the operation has been carried out, even if the status code returned from the origin server indicates that the action has been completed successfully. However, the server SHOULD NOT indicate success unless, at the time the response is given, it intends to delete the resource or move it to an inaccessible location.

A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not include an entity.

If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale. Responses to this method are not cacheable.

Community
  • 1
  • 1
Jordan
  • 2,992
  • 2
  • 20
  • 29
  • I've seen this spec. But what about the other arbitrary methods? How should the browser behave *by default*? – BenMorel May 02 '13 at 13:30
  • It explains it all in this RFC. 200 on successful connect, 202 if status is accepted, 204 for no content. Etc. – Jordan May 02 '13 at 13:32
  • I updated my answer to include a link to the full Spec from the IETF. It goes into detail about message body definitions, etc. – Jordan May 02 '13 at 13:37
  • Please see my comment on @harsh's answer! – BenMorel May 02 '13 at 13:46
  • @Benjamin How about this: http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/ <-- not suggesting you're a dummy. ;) – Jordan May 02 '13 at 13:49
  • please see my updated question for a better understanding of the background! – BenMorel May 02 '13 at 14:49
  • @Benjamin - Have you looked at this? Might help: http://hc.apache.org/httpclient-legacy/tutorial.html – Jordan May 02 '13 at 14:51
  • @Benjamin Also, what language are you using to create this client? – Jordan May 02 '13 at 14:55
  • Although the spec is not very clear about it, I think a PATCH request should include a message-body as well. http://tools.ietf.org/html/rfc5789 – Myrne Stol May 02 '13 at 15:57
  • "the presence of a message-body is signaled by the inclusion of a Content-Length or Transfer-Encoding header" This is what I was looking for. Thanks! – BenMorel May 02 '13 at 16:13
  • @Benjamin Re content-length: I just made a simple HTTP entity cache, and I do console.warn if Content-Length differs from the buffer length given. You could also throw an error. It's not proper, and probably best caught earlier than later. Just the same, it can be nice to set Content-Length based on buffer length (I do that, at least). See https://github.com/meryn/infer-entity-headers/blob/master/src/infer-entity-headers.coffee . – Myrne Stol May 02 '13 at 16:29
  • rfc2616 is obsolete – pjanssen Apr 09 '19 at 09:34
  • @pjanssen Updated – Jordan Apr 09 '19 at 13:02
4

I'm going to answer this:

  1. From the perspective of request-bodies, not response-bodies, as that is what is asked, and of most interest.
  2. In terms of when the body is required, and when it is forbidden.

No request is required to include a body, although the absence of a body might be interpreted as an empty body or one of zero length.

RFC2616 4.3 states:

4.3 Message Body The rules for when a message-body is allowed in a message differ for requests and responses.

...

A message-body MUST NOT be included in a request if the specification of the request method (section 5.1.1) does not allow sending an entity-body in requests.

Going through the methods in 5.1.1 (excluding any extension-methods) you will find:

9.8 TRACE

...

A TRACE request MUST NOT include an entity.

So technically any of the other request methods:

OPTIONS
GET
HEAD
POST
PUT
DELETE
CONNECT

... could include a body. Back to 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.

So in-response to an unexpected entity-body for a particular method or resource, it is safe to ignore it and respond, including the response-code, as if the body was not sent.

Reference: RFC2616 Hypertext Transfer Protocol -- HTTP/1.1

Edit: RFC2616 is well and truly obsolete, refer to RFC7230 for the latest specification.

Community
  • 1
  • 1
javabrett
  • 7,020
  • 4
  • 51
  • 73
3

From your comments I get you're writing an HTTP client library (why, aren't there enough?) and you want to allow for a generic request(method, url[, data]) method. You want to know for what method the data is either required or forbidden.

Just assume the user of your library knows what they're doing. If I want to send a body with a GET request I can, because the spec doesn't forbid that. So why should your library?

Furthermore the HTTP spec is open in this; an extension to HTTP (like WebDAV) can specify new methods (verbs) that do or don't allow or even require a message body.

I think the current effort can better be spent on more important parts.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • Depends on the language you're using, I guess. I've yet to find a properly written browser implementation in PHP for functional testing of controllers (using Request/Response objects, not using the network for the transport, by the way). – BenMorel May 02 '13 at 16:14
0

For arbitrary methods, or valid method which you don't want to support at server side HTTP Status Code 405 should be sent back to caller.

As per http://en.wikipedia.org/wiki/List_of_HTTP_status_codes:

405 Method Not Allowed A request was made of a resource using a request method not supported by that resource;[2] for example, using GET on a form which requires data to be presented via POST, or using PUT on a read-only resource.

harsh
  • 7,502
  • 3
  • 31
  • 32
0

You may want to read the current HTTP spec draft's section about the message body length: http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p1-messaging-22.html#message.body.length

Julian Reschke
  • 40,156
  • 8
  • 95
  • 98