net/http/httputil: NewSingleHostReverseProxy overwrites Director header transformations when hop headers occur #19706
Labels
FrozenDueToAge
NeedsInvestigation
Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone
What version of Go are you using (
go version
)?go version go1.8.typealias linux/amd64
What operating system and processor architecture are you using (
go env
)?GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/usr/local/google/home/piatek/gopath"
GORACE=""
GOROOT="/usr/lib/google-golang"
GOTOOLDIR="/usr/lib/google-golang/pkg/tool/linux_amd64"
GCCGO="/usr/bin/gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build329872370=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
What did you do?
Modified http headers in an httputil.ReverseProxy Director.
What did you expect to see?
The modification applied to the outgoing request.
What did you see instead?
The modifications are reverted when copying hop headers.
As the docs describe, the Director field of an httputil.ReverseProxy is for modifying the request to be sent by the proxy. Headers are a natural thing to change in a Director. This works fine, unless there are hop by hop headers, in which case the ReverseProxy will undo the edits before sending the request.
The problems are here and here:
https://golang.org/src/net/http/httputil/reverseproxy.go#L173
https://golang.org/src/net/http/httputil/reverseproxy.go#L188
The ReverseProxy makes a shallow copy of the request to be sent to the origin. Then, the Director is called, possibly modifying headers. Then, if the ReverseProxy itself decides to modify headers, it copies them from the original request, req.Header, rather than the request passed to the Director, outreq.
My view is that a fix will require an unconditional deep copy of outreq. The existence of the Director API in ReverseProxy seems in conflict with the http.Handler API and a shallow copy. The http.Handler docs prohibit modification of the *http.Request passed to ServeHTTP. Yet, the Director API offers for modification a shallow copy of the *http.Request given to ReverseProxy via ServeHTTP.
The program below reproduces the failure precisely.
The text was updated successfully, but these errors were encountered: