Describe the bug
The spec forbids Content-Length headers on 1xx and 204 responses and on 2xx responses to CONNECT requests. Kestrel should not allow responses to violate this spec.
A server MUST NOT send a Content-Length header field in any response with a status code of 1xx (Informational) or 204 (No Content). A server MUST NOT send a Content-Length header field in any 2xx (Successful) response to a CONNECT request (Section 4.3.6 of [RFC7231]).
https://httpwg.org/specs/rfc7230.html#rfc.section.3.3.2
Furthermore, Kestrel should reject non-zero Content-Length headers on 205 responses considering it disallows writing 205 responses with non-empty bodies and the spec requires this (or an empty chunked body or closing the connection but we use Content-Length: 0 because it performs better):
Since the 205 status code implies that no additional content will be provided, a server MUST NOT generate a payload in a 205 response. In other words, a server MUST do one of the following for a 205 response: a) indicate a zero-length body for the response by including a Content-Length header field with a value of 0; b) indicate a zero-length payload for the response by including a Transfer-Encoding header field with a value of chunked and a message body consisting of a single chunk of zero-length; or, c) close the connection immediately after sending the blank line terminating the header section.
https://httpwg.org/specs/rfc7231.html#rfc.section.6.3.6
|
[StackTraceHidden] |
|
private void ThrowWritingToResponseBodyNotSupported() |
|
{ |
|
// Throw Exception for 204, 205, 304 responses. |
|
throw new InvalidOperationException(CoreStrings.FormatWritingToResponseBodyNotSupported(StatusCode)); |
|
} |
But we also need to make sure that manually setting a non-zero Content-Lenth response header for any of the kinds of responses mentioned above (except 304s) fail since it can never be valid.
Prior discussion: #40882 (comment) and dotnet/yarp#1762.
Expected Behavior
Kestrel should throw before flushing invalid Content-Length headers like it already does for Transfer-Encoding.
Maybe just warning log is justified instead of throwing if the header was Content-Lenth: 0 and it should have simply been omitted, but setting a non-zero Content-Length header on a response that doesn't allow it should always throw.
We need to be careful to still allow Content-Length headers for 304 responses since it is allowed even though it "SHOULD NOT" be generated.
The server generating a 304 response MUST generate any of the following header fields that would have been sent in a 200 (OK) response to the same request: Cache-Control, Content-Location, Date, ETag, Expires, and Vary.
Since the goal of a 304 response is to minimize information transfer when the recipient already has one or more cached representations, a sender SHOULD NOT generate representation metadata other than the above listed fields unless said metadata exists for the purpose of guiding cache updates (e.g., Last-Modified might be useful if the response does not have an ETag field).
https://httpwg.org/specs/rfc7232.html#rfc.section.4.1
Describe the bug
The spec forbids Content-Length headers on 1xx and 204 responses and on 2xx responses to CONNECT requests. Kestrel should not allow responses to violate this spec.
https://httpwg.org/specs/rfc7230.html#rfc.section.3.3.2
Furthermore, Kestrel should reject non-zero Content-Length headers on 205 responses considering it disallows writing 205 responses with non-empty bodies and the spec requires this (or an empty chunked body or closing the connection but we use
Content-Length: 0because it performs better):https://httpwg.org/specs/rfc7231.html#rfc.section.6.3.6
aspnetcore/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs
Lines 1305 to 1310 in c2cba55
But we also need to make sure that manually setting a non-zero Content-Lenth response header for any of the kinds of responses mentioned above (except 304s) fail since it can never be valid.
Prior discussion: #40882 (comment) and dotnet/yarp#1762.
Expected Behavior
Kestrel should throw before flushing invalid Content-Length headers like it already does for Transfer-Encoding.
Maybe just warning log is justified instead of throwing if the header was
Content-Lenth: 0and it should have simply been omitted, but setting a non-zero Content-Length header on a response that doesn't allow it should always throw.We need to be careful to still allow Content-Length headers for 304 responses since it is allowed even though it "SHOULD NOT" be generated.
https://httpwg.org/specs/rfc7232.html#rfc.section.4.1