你正在使用的Go版本是什么( go version
)?
$ go version
net/http/httputil: ReverseProxy
这个问题在最新版本的发布中是否重现?
是
你正在使用什么操作系统和处理器架构( go env
)?go env
输出
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/jzhan/Library/Caches/go-build"
GOENV="/Users/jzhan/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/jzhan/gocode"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/Cellar/go/1.13/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.13/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/4p/ch6dsl490v9227wwhd9rnb7w0000gn/T/go-build248622450=/tmp/go-build -gno-record-gcc-switches -fno-common"
你做了什么?
我正在尝试使用 httputil.Reverseproxy
测试HTTP转发的行为。特别是当后端服务器关闭连接(对于HTTP/1)或重置流(对于HTTP/2)时的行为。为了测试流重置行为,服务器在处理程序中使用了 panic(http.ErrAbortHandler)
。
为这些写了一些测试。
对于HTTP1:https://github.com/jaricftw/go-http-reverseproxy/blob/master/http1_test.go#L20,其中测试了:
1). http1客户端 -> http1服务器
2). http1客户端 -> httputil.Reverseproxy -> http1服务器
对于HTTP2:https://github.com/jaricftw/go-http-reverseproxy/blob/master/http2_test.go#L25,同样:
1). h2c客户端 -> h2c服务器
2). h2c客户端 -> httputil.Reverseproxy(带有h2c设置) -> h2c服务器
你期望看到什么?
我希望所有测试都能通过。也就是说,在流重置场景下,W/和W/O反向代理的响应应该是相同的。
你看到了什么?
在正常情况下,无论是HTTP/1还是HTTP/2,w/和w/o反向代理的测试都通过了。
然而,我发现W/和W/O反向代理在连接/流重置测试用例中有不同的响应:
对于HTTP/1:
W/O reverseproxy:
PASS: TestHTTP1/direct,_server_panic (0.00s)
http1_test.go:62: got err: Get http://127.0.0.1:6666: EOF
http1_test.go:63: got resp: <nil>
W/ reverseproxy:
FAIL: TestHTTP1/via_proxy,_server_panic (0.00s)
http1_test.go:62: got err: <nil>
http1_test.go:63: got resp: &{502 Bad Gateway 502 HTTP/1.1 1 1 map[Content-Length:[0] Date:[Thu, 19 Sep 2019 20:52:56 GMT]] {} 0 [] false false map[] 0xc0001da300 <nil>}
require.go:248:
Error Trace: http1_test.go:65
Error: An error is expected but got nil.
Test: TestHTTP1/via_proxy,_server_panic
对于HTTP/2:
W/O reverseproxy:
PASS: TestHTTP2/direct,_server_panic (0.00s)
http2_test.go:78: got err: Get http://127.0.0.1:7777: stream error: stream ID 3; INTERNAL_ERROR
http2_test.go:79: got resp: <nil>
W/ reverseproxy:
FAIL: TestHTTP2/via_proxy,_server_panic (0.00s)
http2_test.go:78: got err: <nil>
http2_test.go:79: got resp: &{502 Bad Gateway 502 HTTP/2.0 2 0 map[Content-Length:[0] Date:[Thu, 19 Sep 2019 19:01:15 GMT]] 0xc00022e700 0 [] false false map[] 0xc000250800 <nil>}
require.go:248:
Error Trace: http2_test.go:81
Error: An error is expected but got nil.
Test: TestHTTP2/via_proxy,_server_panic
FAIL
4条答案
按热度按时间von4xj4u1#
你好@jaricftw,
在这个场景中,来自反向代理的502似乎对我来说是合理的,但我对http/2.0不如包所有者@bradfitz熟悉。
eyh26e7m2#
@toothrot 我已经更新了这个问题,将HTTP/1也包括在内,似乎反向代理既没有处理HTTP/1连接关闭,也没有处理HTTP/2流重置——客户端将收到默认的502错误。
风险可能是代理在HTTP/1中没有关闭与客户端的连接,或者在HTTP/2中没有向客户端发送
RST_STREAM
?wz1wpwve3#
你可以通过设置自己的ErrorHandler来改变ReverseProxy的默认502行为,具体策略取决于你的需求:https://golang.org/pkg/net/http/httputil/#ReverseProxy.ErrorHandler
风险在于代理在HTTP/1中没有关闭与客户端的连接,或者在HTTP/2中没有向客户端发送RST_STREAM。
抱歉,我不明白。你能重新表述一下吗?或者给我一些背景信息?我阅读了你上面的测试代码(感谢提供的很好的bug报告!),但我对这个最新的陈述/问题感到困惑。
3bygqnnd4#
风险在于代理在HTTP/1中没有关闭与客户端的连接,或者在HTTP/2中没有向客户端发送RST_STREAM?
抱歉,我不明白。您能重新表述一下吗?或者给我一些背景信息?我阅读了您上面的测试代码(感谢您提供的很好的错误报告!),但我对这个最新的陈述/问题感到困惑。
抱歉给您带来困惑。我还没有足够的测试来支持这个观点。我的意思是,代理看到的连接错误没有正确地返回给客户端,这可能会让客户端在收到常规状态码502时感到困惑。例如,客户端可能会根据响应代码/错误选择其重试机制。而且我假设从客户端的Angular 来看,
client <-> proxy
连接/流仍然会被当作“已连接”,尽管proxy->server
已经关闭了?