-
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: timeout error no longer returned from Transport.RoundTrip #16465
Comments
Thanks for an excellent stand-alone test case. FWIW, this behavior changed in 4d2ac54 which was a follow-up to 5dd372b. A patch like, diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index 9164d0d..e715a03 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -1383,7 +1383,9 @@ func (pc *persistConn) readLoop() {
if err == nil {
resp, err = pc.readResponse(rc, trace)
} else {
- err = errServerClosedConn
+ if err == io.EOF {
+ err = errServerClosedConn
+ }
closeErr = err
} ... fixes your test case, but breaks this:
(Note how it becomes flaky) What's happening is that the HTTP transport (client code) is interpreting any read error from the server while the client is idle as the HTTP server just getting bored of us and disconnecting. The errors can take various forms: io.EOF, I suppose we could write a function to detect more of them, but they also vary by OS (Windows vs Unix, especially) and there's nothing in the net package to help us distinguish. Maybe there's something safe we can do for Go 1.7. I'll think. @ianlancetaylor, any thoughts? |
It's probably too special-cased, but what about testing if |
Along those lines, I had been thinking that a |
I should also note: In the real code, I do not care about the type of error that is generated. I care more that the request is aborted should the server not respond. I wrote a test (used to derive the test case in this issue) so I could prove to myself that a timeout was happening. I am OK adjusting how I perform that validation. |
That's approximately what I was thinking.
It is. |
It's kind of weird but for Perhaps we should add a new |
Looking at this more, but one observation: Neither https://golang.org/pkg/net/http/#RoundTripper nor https://golang.org/pkg/net/http/#Transport.RoundTrip make any documentation promises about the type of errors returned, and we obviously have never added unit tests locking in a certain behavior for the past 7 releases. Also, I think this code has changed a fair bit for each of those 7 releases, so I wouldn't be surprised if the exactly handling of this type of error has shifted over time. (though your test does seem to pass with Go 1.5 and Go 1.4 too) |
I've mailed out https://golang.org/cl/25153 which I'm happy with, but it might be too late for Go 1.7. I'll let @ianlancetaylor and @adg chime in. I'm slightly in favor of fixing it for Go 1.7 considering it would mean keeping the behavior from Go 1.4, Go 1.5, and Go 1.6. |
CL https://golang.org/cl/25153 mentions this issue. |
@bradfitz happy for this to go in for 1.7. |
Please answer these questions before submitting your issue. Thanks!
go version
)?go env
)?Create an HTTP transport that supports timeouts; both when dialing and when reading from the established connection.
https://play.golang.org/p/LxGp2ZAI54
The example passes when run in the playground. You need to run this code with 1.7rc2 to see the issue.
With Go 1.6.3, the test program is successful.
With Go1.7rc2, the test program fails because a timeout error is no longer returned.
This is no longer a
net.Error
and also an error that does not support aTimeout
function.The text was updated successfully, but these errors were encountered: