-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net/http: ReadTimeout is not honored when ReadHeaderTimeout > ReadTimeout #35626
Comments
Changing this behavior could break applications. |
@fraenkel I think that isn't true either... I actually assumed as you that this was the case, and tried to use a ReadHeaderTimeout > ReadTimeout in my application. But it turns out it's actually not, and having such a relationship shows an interesting behavior. Observe the following if we alter the example to read:
Then create the following shell script with a client payload:
And run it:
The server happily waits up to ReadHeaderTimeout for headers, but after getting them, if ReadTimeout is elapsed, it instantly times out the request when trying to read the body. (Note therefore that it doesn't affect GET requests where there's no body.) It seems like kind of a useless behavior in real life, and therefore an error for anyone to ever be setting ReadHeaderTimeout > ReadTimeout. I accidentally set ReadHeaderTimeout > ReadTimeout in my application because ReadHeaderTimeout documentation says:
The question is: the read deadline is reset to what? I assumed it would be reset to a new deadline based off of whenever the headers had stopped reading. i.e. that something sensible would happen when ReadHeaderTimeout > ReadTimeout. For example, reset deadline to I think that documentation could also use clarification to indicate what value the read deadline is reset to, and then explicitly call out this interesting behavior as a warning. |
Sorry I should have been more clear. I dont think the current behavior is valuable given what I would have expected the proper behavior to be. If there is no ReadHeaderTimeout, the request timeout is exactly the read timeout. If there is a ReadHeaderTimeout set, the headers must be read within that timeout window, but the request timeout is the remaining amount given the sum of ReadHeaderTimeout + ReadTimeout. What you see above seems correct to me. The header timeout expired and so does the request. For a GET request, having this split timeout doesn't make much sense given there is usually no body. It would have been useful if the timeouts were disconnected so one could guarantee headers are read within time X and bodies within time Y. I guess if one looks at the current ReadHeaderTimeout usage, we could determine if changing the behavior affects people and whether it would be for the better. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
It should.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
The following simple program runs a Hello World HTTP server with 5 second ReadTimeout and 10 second ReadHeaderTimeout.
Start the server. Now, test the timeouts by connecting as a client as follows, where
nc
is the netcat program. The client initiates a connection but never sends any bytes containing request headers.What did you expect to see?
The connection should time out after 5 seconds. The documentation for ReadTimeout states the following:
Since headers are part of the request, we'd also expect this timeout to apply to headers as well.
What did you see instead?
The connection timed out after 10 seconds, not 5 seconds.
NOTE: If we instead did an HTTP POST with a request body included, and then sent the full request (headers+body) in the time between 5 and 10 seconds (with a flush on network connection after sending all headers and before the body), then we would find that the headers would be successfully received by server but then the body would instantly time out when trying to read it. I struggle to see how this would be of any use in the real world, especially seeing as how ServeHTTP cannot adjust read timeouts/deadlines - i.e. lengthen them to something that isn't timing out immediately. (see #16100 )
Suggested action items
I do not know what the actual intended behavior the maintainers of the http package wish to have. It seems to me there are two options to resolve this contradiction:
go/src/net/http/server.go
Line 946 in 440f7d6
The text was updated successfully, but these errors were encountered: