-
Notifications
You must be signed in to change notification settings - Fork 523
Conversation
Let's close #962 then. |
d50bcf1
to
96857f4
Compare
Updated. |
if (_keepAlive && hasConnection) | ||
{ | ||
var connectionValue = responseHeaders.HeaderConnection.ToString(); | ||
_keepAlive = connectionValue.Equals("keep-alive", StringComparison.OrdinalIgnoreCase); | ||
} | ||
|
||
if (!responseHeaders.HasTransferEncoding && !responseHeaders.HasContentLength) | ||
// Set whether response can have body | ||
_canHaveBody = StatusCanHaveBody(StatusCode) && Method != "HEAD"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since 101 status can have a body of sorts, I would prefer _canHaveBody
is true in that case. When deciding whether or not to set Content-Length: 0
we can check for 101 specifically.
{ | ||
// Don't set the Content-Length or Transfer-Encoding headers | ||
// automatically for HEAD requests or 101, 204, 205, 304 responses. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to keep this comment somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will move above if (_canHaveBody)
.
else | ||
{ | ||
// Don't set the Content-Length or Transfer-Encoding headers | ||
// automatically for HEAD requests or 204, 205, 304 responses. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment doesn't makes sense here since no header is being automatically set.
Also, why not reject 101 responses with a Transfer-Encoding?
And why not reject 101/204/205/304 responses with a content-length. It looks like that's also illegal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can 101/204/205/304 have a Content-Length
of 0
(if set)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
If the conditional GET used a strong cache validator (see section 13.3.3), the response SHOULD NOT include other entity-headers. Otherwise (i.e., the conditional GET used a weak validator), the response MUST NOT include other entity-headers; this prevents inconsistencies between cached entity-bodies and updated headers.
Entity-headers include Content-Length, but I don't know anything about strong cache validators, so I guess there is some wiggle room. The other status codes don't seem to mandate anything.
Where is the spec requiring that Transfer-Encoding
header can't be sent? Like Content-Length
it doesn't really make sense, and we wouldn't set it automatically, but where is it explicitely prohibited?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://tools.ietf.org/html/rfc7230#section-3.3.1
Transfer-Encoding MAY be sent in a response to a HEAD request or in a 304 (Not Modified) response (Section 4.1 of [RFC7232]) to a GET request, neither of which includes a message body, to indicate that the origin server would have applied a transfer coding to the message body if the request had been an unconditional GET. This indication is not required, however, because any recipient on the response chain (including the origin server) can remove transfer codings when they are not needed.
A server MUST NOT send a Transfer-Encoding header field in any response with a status code of 1xx (Informational) or 204 (No Content). A server MUST NOT send a Transfer-Encoding header field in any 2xx (Successful) response to a CONNECT request (Section 4.3.6 of [RFC7231]).
Has lots more here
A sender MUST NOT send a Content-Length header field in any message that contains a Transfer-Encoding header field.
A user agent SHOULD send a Content-Length in a request message when no Transfer-Encoding is sent and the request method defines a meaning for an enclosed payload body. For example, a Content-Length header field is normally sent in a POST request even when the value is 0 (indicating an empty payload body). A user agent SHOULD NOT send a Content-Length header field when the request message does not contain a payload body and the method semantics do not anticipate such a body.
A server MAY send a Content-Length header field in a response to a HEAD request (Section 4.3.2 of [RFC7231]); a server MUST NOT send Content-Length in such a response unless its field-value equals the decimal number of octets that would have been sent in the payload body of a response if the same request had used the GET method.
A server MAY send a Content-Length header field in a 304 (Not Modified) response to a conditional GET request (Section 4.1 of [RFC7232]); a server MUST NOT send Content-Length in such a response unless its field-value equals the decimal number of octets that would have been sent in the payload body of a 200 (OK) response to the same request.
etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: Not saying my logic was completely right according to spec - it seems to have got bigger since I read it last (which it also obviously hasn't... 😟)
if (Method == "HEAD") | ||
{ | ||
// Don't write to body for HEAD requests. | ||
Log.ConnectionHeadResponseBodyWrite(ConnectionId, count); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have a flag so this is only logged once per request/response? Maybe log it at the end of the response so we can count the size of all the writes.
@halter73 I've addressed your feedback. |
@@ -548,9 +548,6 @@ public void ConnectionCanReadAndWrite(TestServiceContext testContext) | |||
"POST / HTTP/1.1", | |||
"Content-Length: 3", | |||
"", | |||
"101POST / HTTP/1.1", | |||
"Content-Length: 3", | |||
"", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's weird to set a 101 response and complete without writing anything, but this is still a valid test case right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
101 is now closed after response so that made this test fail. That's why I added the new test.
{ | ||
await connection.SendEnd( | ||
"GET / HTTP/1.0", | ||
"Connection: kee-alive", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kee-alive
@@ -75,6 +75,8 @@ public abstract partial class Frame : IFrameControl | |||
protected readonly long _keepAliveMilliseconds; | |||
private readonly long _requestHeadersTimeoutMilliseconds; | |||
|
|||
private int _responseBytesWritten; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be long. Maybe call this _responseBytesIgnored since we're only using it to log the number of bytes not written.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll use it when fixing #175, so less diff when I make that change 😄
@@ -542,6 +547,8 @@ public Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationTo | |||
return WriteAsyncAwaited(data, cancellationToken); | |||
} | |||
|
|||
_responseBytesWritten += data.Count; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be done just in the !_canHaveBody case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above.
db1b445
to
9ec8bf0
Compare
Updated. |
I would also like to see the /plaintext benchmark results for this. |
dev
PR
Usual fluctuation seen across multiple runs. |
- Add functional tests - Remove BadHttpResponse, ResponseRejectionReasons and TestFrameProtectedMembers - Chunk non-keepalive HTTP/1.1 responses - Set _canHaveBody to true when StatusCode == 101 - Add test to check that upgraded connections are always closed when the app is done - Log writes on responses to HEAD requests only once.
9ec8bf0
to
4117ad8
Compare
Rebased @benaadams's #962 and made some changes.
Like the original PR, this addresses #952.
@halter73 @benaadams @Tratcher