go: net/http/httputil: Proxy terminates HTTP/2 stream before reading response body.
Please answer these questions before submitting your issue. Thanks!
1. What version of Go are you using (go version
)?
go version go1.7 darwin/amd64
2. What operating system and processor architecture are you using (go env
)?
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
3. What did you do?
- Running a reverse proxy using https://golang.org/pkg/net/http/httputil/
- Proxies HTTP on host:port to a target server defined by the
-proxy
flag. - Sending POST data through the proxy (the proxy manipulates CORS headers)
4. What did you expect to see?
- A HTTP 200 (or other successful status code).
5. What did you see instead?
- A HTTP 502 and a proxy error due to premature termination of the HTTP/2 stream.
go run simple.go -proxy=https://repeater.getattest.io/post/data -port=8001
curl http://localhost:8001/post/data -d "gophers=yes;"
ts="2016/08/18 06:40:38" msg="http: proxy error: stream error: stream ID 3; STREAM_CLOSED"
ts=2016-08-18T06:40:38-07:00 status=502 method=POST uri=https://repeater.getattest.io/post/data duration=20.74786ms bytes=0 from=127.0.0.1:56479
- The proxy I’m running (single file): https://gist.github.com/elithrar/a47af11adb818571d364cc5797ce0fb6 - run it, then hit with the curl above. Updated with simpler code
- The upstream, in this case, is nginx (CloudFlare; HTTP/2), fronting my test server (Go on Heroku HTTP/1.1).
- Running
binaryname -proxy=https://post.workwithgo.com/post/data
(Caddy, HTTP/2, proxying the same origin application) and running the same curl does not cause the same error. - To be tested: nginx mainline over HTTP/2, which appears to be the last remaining variable.
Note: Disabling HTTP/2 via a custom transport on the upstream leg avoids the issue (as you would expect, given the error). I have yet to test on another HTTP/2 origin (I’ll spin up a raw Caddy instance shortly).
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 1
- Comments: 19 (8 by maintainers)
Commits related to this issue
- http2: fix protocol violation regression when writing certain request bodies The mod_h2 workaround CL (git rev 28d1bd4, https://golang.org/cl/25362) introduced a regression where the Transport could ... — committed to golang/net by bradfitz 8 years ago
- [release-branch.go1.7] net/http: update bundled http2 for Transport double STREAM_ENDED error Updates bundled http2 to x/net/http2 git rev 7394c11 for: http2: fix protocol violation regression when ... — committed to golang/go by bradfitz 8 years ago
- [release-branch.go1.7] http2: fix protocol violation regression when writing certain request bodies The mod_h2 workaround CL (git rev 28d1bd4, https://golang.org/cl/25362) introduced a regression whe... — committed to golang/net by bradfitz 8 years ago
Whoa, this is messed up:
Two END_STREAM bits for the same stream ID (13).
No wonder the server on the other side is telling us RST_STREAM. I’m surprised it’s not just hanging up on us for a protocol error violation.
(To be clear, because your comment looks backwards, @elithrar: the Go HTTP/2 client appears to be writing bogus frames, and then the server is writing RST_STREAM stream=13 len=4 ErrCode=STREAM_CLOSED, which the proxy’s HTTP client then reads.)