-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: unexpected 1XX status codes are not handled well #17739
Comments
/cc @bradfitz |
Yeah, we don't support anything other than "100 Continue". I suppose the Transport could have an optional callback func to handle other 1xx responses. @Lukasa, which 1xx responses are used in the wild? I've never really seen anything. |
101 is obvious but a special case. 102 is used in WebDAV. Most importantly the HTTPbis is considering specifying a 103 for delivering Link headers early, and there has been push-back on having that response be negotiated like 100 or 101 are. So that would mean that, if specified, Go clients could hit it when communicating with web servers. Not ideal. |
With or without something like |
I have strongly argued for with, but a couple of folks including Roy Fielding have argued very emphatically for without. |
/cc @tombergan for thoughts. |
Yeah, I followed the ietf-http-wg thread that @Lukasa is referencing. I had intended to file a bug at the time, but I forgot, and it looks like @Lukasa beat me to it. Here are the relevant messages, with various degrees of curmudgeony: RFC 7231 is clear that the Go library mishandles 1xx requests:
Note the proxy case. In order to write a spec-compliant proxy in Go, the proxy needs to forward 1xx responses, which means the proxy must be allowed to call |
Okay, let's fix this in Go 1.10. We probably want to put some bounds on the number of bytes and/or number of 1xx header messages. |
@bradfitz, I can think of three ways to allow clients to handle 1xx responses:
I don't like (1) because it will be awkward to tie each callback to a request. Slight preference for (3) because that mechanism already exists. Thoughts? |
|
Compared to (3), (4) has the disadvantage that we add a new API, but the advantage that (3) cannot import http types directly (like |
I think this issue conflates a bigger, easier problem with a smaller, harder problem. The bigger, easier problem is that the Go HTTP client is completely confused by 1xx responses other than a single 100 (Continue), in clear violation of the protocol, hampering interoperability with RFC 8297 among other things. It can be trivially fixed by replacing The smaller, harder problem is that the Go HTTP client doesn’t provide an API for 1xx responses, which precludes building a correct HTTP proxy on top of it. But I don’t think this should prevent or delay fixing the bigger, easier problem. As far as I’m aware, the Go distribution doesn’t even include an HTTP proxy ( Would you like me to submit the above fix to |
The RFC you linked says:
|
If you'd like, but I was also planning on working on this during the Feb/Mar/Apr dev cycle for Go 1.11. |
Yes, but it also says:
and elsewhere the RFC 723x series of documents distinguishes clearly between proxies and gateways, so the text quoted by @tombergan should not be taken as applying to gateways. |
Change https://golang.org/cl/116855 mentions this issue: |
…operly Previously the Transport had good support for 100 Continue responses, but other 1xx informational responses were returned as-is. But per https://tools.ietf.org/html/rfc7231#section-6.2: > A client MUST be able to parse one or more 1xx responses received > prior to a final response, even if the client does not expect one. A > user agent MAY ignore unexpected 1xx responses. We weren't doing that. Instead, we were returning any 1xx that wasn't 100 as the final result. With this change we instead loop over up to 5 (arbitrary) 1xx responses until we find the final one, returning an error if there's more than 5. The limit is just there to guard against malicious servers and to have _some_ limit. By default we ignore the 1xx responses, unless the user defines the new httptrace.ClientTrace.Got1xxResponse hook, which is an expanded version of the previous ClientTrace.Got100Continue. Still remaining: * httputil.ReverseProxy work. (From rfc7231#section-6.2: "A proxy MUST forward 1xx responses unless the proxy itself requested the generation of the 1xx response."). Which would require: * Support for an http.Handler to generate 1xx informational responses. Those can happen later. Fixing the Transport to be resilient to others using 1xx in the future without negotiation (as is being discussed with HTTP status 103) is most important for now. Updates #17739 Change-Id: I55aae8cd978164643fccb9862cd60a230e430486 Reviewed-on: https://go-review.googlesource.com/116855 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
This is fixed enough by CL 116855 above. I'll file separate bugs for the remaining bits. |
Change https://golang.org/cl/123615 mentions this issue: |
Updates golang/go#26189 (fixes after vendor into std) Updates golang/go#17739 Change-Id: I076cdbb57841b7dbbaa764d11240913bc3a8b05d Reviewed-on: https://go-review.googlesource.com/123615 Reviewed-by: Ian Lance Taylor <[email protected]>
Change https://golang.org/cl/123675 mentions this issue: |
I both forgot that this list could contain duplicates, and I had forgot to run the net/http tests against CL 123615 before mailing it, which ended up catching this bug. The diff of this file from the commit before CL 123615 (a45b4ab^ == cffdcf6) to this commit is: https://gist.github.com/bradfitz/0b7abf8fa421515aed9c4d55ce3a1994 ... effectively reverting much of CL 123615 and just moving the 1xx handling down lower. Updates golang/go#26189 (fixes after vendor into std) Updates golang/go#17739 Change-Id: Ib63060b0bb9721883b4b91a983b6e117994faeb9 Reviewed-on: https://go-review.googlesource.com/123675 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Andrew Bonventre <[email protected]>
Change https://golang.org/cl/123676 mentions this issue: |
Updates bundled x/net/http2 to git rev d0887baf81f4 for: http2: ignore unknown 1xx responses like HTTP/1 https://golang.org/cl/123615 http2: fix bug in earlier CL 123615 https://golang.org/cl/123675 Also along for the ride, but without any effect: http2: export a field of an internal type for use by net/http https://golang.org/cl/123656 Fixes #26189 Updates #17739 Change-Id: I1955d844d74113efbcbbdaa7d7a7faebb2225b45 Reviewed-on: https://go-review.googlesource.com/123676 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?go version go1.7.3 darwin/amd64
What operating system and processor architecture are you using (
go env
)?What did you do?
Running the following Python test server:
I ran the following Go test client against it:
What did you expect to see?
I expected to see a 200 status code and the HTML body from the 200 response.
What did you see instead?
Go reported the 103 status code as final with no body, and did not provide access to the 200 response.
The text was updated successfully, but these errors were encountered: