HTTP Transfer-Encoding and requests - http

the HTTP specification states that the Transfer-Encoding header is allowed for requests - but what error code should a server respond if it doesn't understand that given Transfer-Encoding.
As far as I know the HTTP standard doesn't cover this possibility, but maybe I have just overlooked it.

An unknown transfer-encoding should raise a HTTP error 501 "NOT IMPLEMENTED".
That's what Apache does, at least.
Also see http://argray.com/unixfaq/httpd_error_codes.shtml
Edit: pointer to the corresponding RFC section: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.2

I agree that the answer to this is non-obvious, and have followed up on the HTTP WG's mailing list.
UPDATE: Björn H. rightfully points out:
Section 3.6 of RFC 2616:
A server which receives an
entity-body with a transfer-coding it
does not understand SHOULD return
501 (Unimplemented), and close the
connection.
So it does address this already.

Mostly a personal opinion.
i always thought 5xx errors were actual programming errors, like something fell over. If a server doesnt understand the request i would say a 4xx error is a better response as the problem is with the request not so a failed process on the server. Im not sure which 4xx but there are a few so selecting one should not be hard.

A request with an invalid Transfer-Encoding for the HTTP version is malformed. Therefore, the server should respond with 400 Bad Request.

Arguably failing to understand chunked encoding ought to be a 500 Internal Server Error rather than 501, because RFC-2616 says the server MUST understand it.
However, if a server chooses not to accept requests with chunked bodies, and it wants to blame the client for this, one way to do so legally would be 411 Length Required -- since one must not use Content-Length and Transfer-Encoding at the same time, and it is not practical to send a request without either anyway.

The RFC is a bit unclear, but IMHO it should be 406 Not Acceptable.

Related

Is a standard-compliant (RFC 7230) HTTP-server allowed to respond with only 400 Bad Request?

A question that arose while reading the RFC 7230: Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing was "what is the simplest possible server that this would be compliant with this standard". Searching for "MUST" in the document, it seems to me that the only responses a server has to return is a 400-error, in the case of the request being malformed:
A
server MUST reject any received request message that contains
whitespace between a header field-name and colon with a response code
of 400 (Bad Request).
(3.2.4. Field Parsing)
If a Transfer-Encoding header field
is present in a request and the chunked transfer coding is not
the final encoding, the message body length cannot be determined
reliably; the server MUST respond with the 400 (Bad Request)
status code and then close the connection.
(3.3.3. Message Body Length .3)
If this is a
request message, the server MUST respond with a 400 (Bad Request)
status code and then close the connection.
(3.3.3. Message Body Length .4)
among others.
There are some cases where the standard dictates that the server MUST return a certain status code, but they all seem to be made optional by some stronger clause, for example:
If a server receives both an Upgrade and an Expect header field with
the "100-continue" expectation (Section 5.1.1 of [RFC7231]), the
server MUST send a 100 (Continue) response before sending a 101
(Switching Protocols) response.
(6.7 Upgrade)
being made optional by
A server MAY ignore a received Upgrade
header field if it wishes to continue using the current protocol on
that connection. Upgrade cannot be used to insist on a protocol
change.
(6.7 Upgrade)
All of this leads me to believe that a 400-only server is technically allowed by the standard.
This does seem rather odd to me, I thought a 400-header meant that the request itself was malformed in some way and that a server had to respond with some other error iff the request was well-formed but invalid in some other way.
Have I missed something in the standard, or some other relevant standard, or is a 400-only server allowed?
(As a side note, section 2.6 states
A server can send a 505
(HTTP Version Not Supported) response if it wishes, for any reason,
to refuse service of the client's major protocol version.
which leads me to believe a 505-only server would actually be allowed, although quite boring)

Jetty returning "HTTP/1.1 400 Bad Request" on malformed HTTP POST header. Is this expected?

does having a space in the http post headers result in BAD request??
I see this in one of the requests:
Content-Type "text/xml; c harset=utf-8"
and I get a HTTP/1.1 400 Bad Request
But if the same request is posted with
Content-Type "text/xml; charset=utf-8"
i.e no space in charset it works.
In my implementation I am not doing any validation.
So I am assuming my Jetty server throws a bad request since there is a space in charset??
Am I right or is my interpretation wrong.
Thanks!!
Yes, having a space where you are putting it should result in a bad request.
HTTP 1.1 is a protocol defined by a standard. By referencing the standard documentation, it is possible to determine what is and what isn't a valid request.
You can find the standard for HTTP/1.1 at RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1, and you might specifically want to look at sections 14.17 Content-Type and 3.7 Media Types.
Essentially, by inserting the space into "charset", you are creating an invalid HTTP request because the protocol doesn't understand the "c" and "harset" portions. Those aren't defined as valid text in that context.
Moreover, while the protocol knows what appears to be valid and what doesn't, it isn't intelligent enough to infer how to fix even a simple typo like this. As such, for the server to respond "400 Bad Request" is appropriate and conforming to the protocol standard. For what it's worth, you'll also find the HTTP status codes in the RFC. Status code 400 Bad Request means:
The request could not be understood by the server due to malformed
syntax. The client SHOULD NOT repeat the request without
modifications.
i.e. Don't do that. :)

How to tell there's something wrong with the server during response that started as 200 OK. Fail gracefully

I am qurious if there is any standard method in HTTP 1.X protocol to tell there is a problem on the server during http response that started as 200 OK.
How to tell there's any error on the server if 200 OK header is already returned and we are currently sending the response body? In some standards-compilliant way.
UPD : There is a duplicate, but without a single answer (!) HTTP: error during reply after 200 OK status code.
To be specific: I can not use Content-Length for checking at response end, because the length can't be known at response start.
Additionaly, I can't cache the whole response on the server before sending (because it is too big and I will run out of memory, and it's too long to generate so the user can't wait, etc...).
There is no standard method to do what you want.
To be precise, the standard method is to buffer the response on the server, then send a 200 OK and the Content-Length, followed by the content. As stated, this does not work for you.
The only alternative I can think of, is to wrap the content in some format that makes it discoverable whether it was sent correctly. For example, you might end it with a hash or even a digital signature. But obviously, such mechanisms are not part of the HTTP standard.

Chunked encoding and content-length header

Is it possible to set the content-length header and also use chunked transfer encoding? and does doing so solve the problem of not knowing the length of the response at the client side when using chunked?
the scenario I'm thinking about is when you have a large file to transfer and there's no problem in determining its size, but it's too large to be buffered completely.
(If you're not using chunked, then the whole response must get buffered first? Right??)
thanks.
No:
"Messages MUST NOT include both a Content-Length header field and a non-identity transfer-coding. If the message does include a non-identity transfer-coding, the Content-Length MUST be ignored." (RFC 2616, Section 4.4)
And no, you can use Content-Length and stream; the protocol doesn't constrain how your implementation works.
Well, you can always send a header stating the size of the file.
Something like response.addHeader("File-Size","size of the file");
And ignore the Content-Length header.
The client implementation has to be tweaked to read this value, but hey you can achieve both the things you want :)
You have to use either Content-Length or chunking, but not both.
If you know the length in advance, you can use Content-Length instead of chunking even if you generate the content on the fly and never have it all at once in your buffer.
However, you should not do that if the data is really large because a proxy might not be able to handle it. For large data, chunking is safer.
This headers can be cause of Postman Parse Error:
"Content-Length" and "Transfer-Encoding" can't be present in the response headers together.
Using parametrized ResponseEntity<?> except raw ResponseEntity in controller can fixed the issue.
The question asks:
Is it possible to set the content-length header and also use chunked transfer encoding?
The RFC HTTP/1.1 spec, quoted in Julian's answer, says:
Messages MUST NOT include both a Content-Length header field and a non-identity transfer-coding.
There is an important difference between what's possible, and what's allowed by a protocol. It is certainly possible, for example, for you to write your own HTTP/1.1 client which sends malformed messages with both headers. You would be violating the HTTP/1.1 spec in doing so, and so you'd imagine some alarm bells would go off and a bunch of Internet police would burst into your house and say, "Stop, arrest that client!" But that doesn't happen, of course. Your request will get sent to wherever it's going.
OK, so you can send a malformed message. So what? Surely on the receiving end, the server will detect the HTTP/1.1 protocol client-side violation, vanquish your malformed request, and serve you back a stern 400 response telling you that you are due in court the following Monday for violating the protocol. But no, actually, that probably won't happen. Of course, it's beyond the scope of HTTP/1.1 to prescribe what happens to misbehaving clients; i.e. while the HTTP/1.1 protocol is analogous to the "law", there is nothing in HTTP/1.1 analogous to the judicial system.
The best that the HTTP/1.1 protocol can do is dictate how a server must act/respond in the case of receiving such a malformed request. However, it's quite lenient in this case. In particular, the server does not have to reject such malformed requests. In fact, in such a scenario, the rule is:
If the message does include a non-identity transfer-coding, the Content-Length MUST be ignored.
Unfortunately, though, some HTTP servers will violate that part of the HTTP/1.1 protocol and will actually give precedence to the Content-Length header, if both headers are present. This can cause a serious problem, if the message visits two servers in sequence in the same system and they disagree about where one HTTP message ends and the next one starts. It leaves the system vulnerable to HTTP Desync attacks a.k.a. Request Smuggling.

Why would a server not set a HTTP Response Code?

I'm asking in generalities - why would any server not set and return headers and/or status codes? I can't think of a good reason for this. Perhaps I'm overlooking something.
The Status-Code is a required part of a HTTP Response.
By definition, the only reason for a server not to provide a Status-Line is that it is not a HTTP server.
RFC 2616, section 6: Response.
Or said in a slightly less pedant way: if it does this, the server is hopelessly buggy and you should run away from it screaming.
Status codes were introduced in HTTP/1.0 - prior to this, things were much simpler - there were no headers in the request or the response.
A request was simply like this, with no indication of the protocol version
GET /
The response would be all body, with no headers.
So it looks like you are talking to some kind of antique webserver which only speaks HTTP/0.9!

Resources