Is an HTTP PUT request required to include a body? - http

I'm having trouble finding a definite specification of this in the standard. I have an HTTP client that's not including a Content-Length: 0 header when doing a PUT request where I don't specify a body, and a server that gets confused by such requests, and I'm wondering which program I should be blaming.

HTTP requests have a body if they have a Content-Length or Transfer-Encoding header (RFC 2616 4.3). If the request has neither, it has no body, and your server should treat it as such.
That said it is unusual for a PUT request to have no body, and so if I were designing a client that really wanted to send an empty body, I'd pass Content-Length: 0. Indeed, depending on one's reading of the POST and PUT method definitions (RFC 2616 9.5, 9.6) one might argue that the body is implied to be required - but a reasonable way to handle no body would be to assume a zero-length body.

Not answering the question, but asserting how jaxrs allows me to frequent use of bodyless PUTs:
Example of bodyless put:
Give user an additional permission.
PUT /admin/users/{username}/permission/{permission}

A body is not required by the IETF standard, though the content-length should be 0 if there's no body. Use the method that's appropriate for what you're doing. If you were to put it into code, given
int x;
int f(){ return x; }
and a remote variable called r.
A post is equivalent to
r=f();
A put is equivalent to
r=x;
and a get is equivalent to
x=r;

What is being PUT (in the verb sense) onto the server if there's no content? The spec refers to the content as "the enclosed entity", but a request with no content would have no enclosed entity, and therefore nothing to put on the server.
Unless, of course, you wanted to PUT nothing onto the server, in which case you'd probably want a DELETE instead.

The content length field is required as per the following section in the HTTP/1.1 standard http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13

Related

How many URLs/URIs in an HTTP POST request, and what are they?

Questions like this and material like this provide lots of useful information about HTTP POST... but none that I have found clarifies the role of that second URL (or is it a URI, or something else, and is it even secondary?) in the very first line of the POST request header:
POST /second/url/here/ HTTP/1.1
The request itself is sent to a URL (URI?), which feels "primary" to me in some sense. Can someone please clarify the role of both, and why they would be the same or different as seems to be possible?
(P.S. it was probably once so obvious that nobody thought it might ever need explaining. But now when you google for "HTTP POST", half the internet appears, and it's near impossible to see the forest for the trees...)
I don't know hat is the 1st and the 2nd URL for you. I see only one. And it's not in the body but in the first line.
L01 POST /something?query=string HTTP/1.1\r\n
L02 Host: www.example.com\r\n
L03 Foo: here another header content\r\n
L04 Content-Length: 26\r\n
L05 \r\n
L06 This=is+the+body&arg=val\r\n
Let's analyze this from the bottom:
L06: this is the body, with a size of 26 octets, and containing some data, format of this body may be more complex, like being fom-url-encoded, gzipped, may contain some other \r and \n, etc. Depends on the list of headers.
L05: body separator
L04: one of the headers, with the size of the body
L03: another header (you can have plenty of headers)
L02: important header, the Host header must be used on HTTP version 1.1, to tell the server which Virtualhost you really want
L01: the first line.
The ** first line** is:
METHOD URL PROTOCOL
Where:
METHOD: is POST
URL: is /something?query=string, everything after the ? is the query string, which does not indicate a document (this is the job of the first part) but some extra parameters (the only one you can use with GET queries).
PROTOCOL: is HTTP/1.1, means you are talking with version 1.1 of the HTTP protocol

Is it valid to return a body along with an Http 204 status?

We're currently working to the OData standard:
http://www.odata.org/developers/protocols/operations
According to this standard, if you perform an PUT operation against your data, you should return a 204 status code. The standard says that:
When processing a PUT request servers return status 204 (No Content)
to indicate success, no response body is needed.
Now, according to what one reads elsewhere, some places claim that if you're returning a 204 you should absolutely NOT return a response body - it's not a question of whether one is needed or not.
The problem is we kind of need to return a body. In this case we're performing an update query on a batch of items and partial success (i.e. some are updated, some are not) is possible. We'd like to inform the client of what the failures were and the response body is the only way of doing it that I can think of.
So what's the "correct" way of doing this. Should I flout the W3C and return a body? Or should I flout OData and return a different response code? Or is there another possibility?
The 204 response to PUT is not a mandatory requirement for OData servers (note that the odata.org is not a normative reference, the MS-OData document is). You can return 200 with body, in which case the body you return should be a serialization of the updated entity (after the updates were applied by the server). In fact in OData V3 we now have a support for Prefer header which does exactly this. The client can include a Prefer header with the PUT request and ask the server to respond with 200 and the updated entityt.
I think you must not return content and should consider returning a header to indicate the partially complete command.
The spec states
The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.
You may also wish to take the batch approach, http://www.odata.org/developers/protocols/batch
You shouldn't return 204 unless the operation succeeded completely.
Seems weird to return a 204 for a PUT. I always thought 204 paired with the DELETE. Where the text 'no content' means that the resource is no longer on the server. The PUT doesn't have anything to do with removing resources so shouldn't use 204. Also 204 is a success code so should be used when 100% successful.

Are PUT and POST requests required/expected to have a request body?

I'm writting a RESTful api, and at I'm thinking about the process of a user creating a key. I have the following possibilities:
GET request to /new/<keyname> - although it's very easy I think I won't use this, because I heard GET is for retrieving and/or listing information;
POST request to /<keyname> - This seemed to me easy and simple enough, but does not pass any data in the request body. Can I do it this way ? Is this weird ?
POST request to /keys passing in the request body "keyname=SomeKey" - Is this the correct way ?
I looked at this API from joyent and in all their PUT and POST requests they pass some data in the request body. Is this expected ? Is it really wrong not to require a request body in a PUT and POST request ?
I asked this question on the Http-WG. This was the most precise answer I got http://lists.w3.org/Archives/Public/ietf-http-wg/2010JulSep/0276.html
In summary, POST does not require a body. I would expect the same justification can be applied to PUT.
RFC2616 is the base RFC for HTTP 1.1
In the most general form, an HTTP message is this (note the optional body):
generic-message = start-line
*(message-header CRLF)
CRLF
[ message-body ]
start-line = Request-Line | Status-Line
Reading further gives this:
9.5 POST
The POST method is used to request that the origin server accept the
entity enclosed in the request as a new subordinate of the resource
identified by the Request-URI in the Request-Line. ...
and
9.6 PUT
The PUT method requests that the enclosed entity be stored under the
supplied Request-URI. ...
The fundamental difference between the POST and PUT requests is
reflected in the different meaning of the Request-URI. The URI in a
POST request identifies the resource that will handle the enclosed
entity. That resource might be a data-accepting process, a gateway to
some other protocol, or a separate entity that accepts annotations.
In contrast, the URI in a PUT request identifies the entity enclosed
with the request -- the user agent knows what URI is intended and the
server MUST NOT attempt to apply the request to some other resource.
Both POST and PUT include the phrase entity enclosed in the request.
Based on my reading, I believe that a body is desired (a non-normative description, I know) for both POST and PUT.
In the context of REST, POST is create and PUT is update. I can imagine creating an empty object (perhaps a placeholder for future information), but I don't imagine much use of an empty update.
It is not required. You can send a POST/PUT request without a body and instead use query string parameters. But be careful if your parameters contain characters that are not HTTP valid you will have to encode them.
For example if you need to POST 'hello world' to and end point you would have to make it look like this: http://api.com?param=hello%20world
Probably the best way is your third option: POST to /keys with keyname=SomeKey.
Here's why: You may wish to add another function to your API, for example create_new_user. It would then be difficult to tell the difference between a user trying to POST a key called create_new_user and a user trying to use the create_new_user function.
You are correct in saying that you should not be using GET to do this operation as the GET operation "SHOULD NOT have the significance of taking an action
other than retrieval." (RFC 2616).
To answer your question in one line. Yes it is expected to have Body/Content in body, but it is not required(Mandatory).
According to okHttp3 (an HTTP library for android): the following methods need a body: POST, PUT, PATCH, PROPPATCH (WebDAV) and REPORT (source). It even crashes if you try to do a request with the given methods without a body.

Is it possible to set some http headers while http-redirect(302 or 307)?

Is it possible to set some http headers while http-redirect(302 or 307)?
<?
header("some-header: xxx");
header("Location: http://other.domain.com/foo.php",TRUE,307);
?>
You can basically set whatever http headers you want either as the server or the client.
If you are indicating a redirect you should supply the Location header as your example suggests. You should also ensure that your response headers refer to that response rather than the resource that the client is being redirected to. i.e. your headers here could include Content-Length: 0, omit the Content-Type header and so on.
Not sure if this is what you're after - this question could do with a bit more detail.
You can always do the redirection 301/307.
There are ways to do it
1) Do it through java code :
response.setStatus(307);
response.setHeader("Location",url);
2) THe same thing can be done in JSPs.
A tip here is: Always use the setHeader function and not the addHeader function as they behave in different ways.

Can I send a HTTP redirect to a url with an anchor?

Is it possible to send a response with 302 status code to a url like this:
http://mysite.com/something/#somethingelse
Yes, you can use the fragment identifier. This was a known bug in the HTTP spec, fixed in subsequent revisions of the spec. See RFC 9110.
Following the HTTP specification, the value for the Location header field must be an absoluteURI value. And that is according to the RFC 3986 (they just changed the name from absoluteURI to absolute-URI):
absolute-URI = scheme ":" hier-part [ "?" query ]
So theoretically the fragment is not allowed as part of the value. But the browsers can handle it.
With strict reading RFC2616 does not allow fragments in Location header values, since they are not part of absolute URIs. However, with the IETF's HTTP rewrite draft this was fixed.
Recently Julian put up a comparison how browsers handle URI fragments (that's what the HTML anchor tags deal with) in the Location header: http://www.greenbytes.de/tech/tc2231/redirects.html
So the answer ist: Yes, you can put fragments in Location header URIs.
There appears to be no problem in doing so from PHP:
Header(
"Location: http://en.wikipedia.org/wiki/HTTP#Status_codes",
true,
302
);
Yes. It's the browser which doesn't send the hash to the server, not the other way around.
While the original RFC 2616 allowed only absoluteURI in the Location header, as the other (older) answers explain, the current RFC 7231 allows any URI-reference, either a full URI (with fragment possibly included), or even a relative URI, resolved against the current effective URI. And it even explicitly describes the behavior of fragments during redirection (if the Location header includes the fragment, it is used, if not, the original fragment is inherited and applied after the redirection).
I.e. yes, you can, it is even officially standardized now.

Resources