Skip to content
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/httputil: The ReverseProxy's director cannot communicate failure #34733

Closed
iselind opened this issue Oct 7, 2019 · 3 comments
Closed

Comments

@iselind
Copy link

iselind commented Oct 7, 2019

What version of Go are you using (go version)?

$ go version
go version go1.12.9 linux/amd64

Does this issue reproduce with the latest release?

Not related to specific Go release

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/patriki/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/patriki/go"
GOPROXY="direct"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
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 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build120897579=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I use a ReverseProxy from the httputil package.

The director field in the reverse proxy struct cannot communicate that the 'rebuilding' of the request failed. Hence, there's no way for the director to stop the request from being transported further.

What did you expect to see?

The director should be able to return an error or by some other means tell the reverse proxy that it failed making the resulting request broken.

The result of the director failing should probably be something along the lines of HTTP 500/502 error being returned to the client and the request not sent anywhere.

What did you see instead?

The request gets sent along as if the director succeeded, even if it didn't

@bradfitz
Copy link
Contributor

bradfitz commented Oct 7, 2019

For go1compat reasons, we can't change the signature, so your best bet is probably to supply a custom Transport or just have your own http.Handler/HandlerFunc that validates the request before you delegate to ReverseProxy.ServeHTTP. The ReverseProxy is just another http.Handler which are all composable.

@bradfitz bradfitz closed this as completed Oct 7, 2019
@iselind
Copy link
Author

iselind commented Oct 8, 2019

Thanks for the guidance, much appreciated.

Isn't this something that could be amended next time the API is broken anyway? In my opinion, this should really be fixed so we don't have to resort to hackish solutions around this forever.

@kheraud
Copy link

kheraud commented Apr 22, 2020

Thanks for the issue, it leads me to this hack

var internalErrorHeader = "X-Routing-Error"

type roundTripperFilter struct {
	parent http.RoundTripper
}

func (rtf *roundTripperFilter) RoundTrip(r *http.Request) (*http.Response, error) {
	if err, ok := r.Header[internalErrorHeader]; ok {
		return nil, errors.New(strings.Join(err, ","))
	}
	return rtf.parent.RoundTrip(r)
}

myProxy := httputil.ReverseProxy{
	Director: myDirector,
	Transport: &roundTripperFilter{
		parent: func(r *http.Request) {
			r.Header.Add(internalErrorHeader, "An error occured in ReverseProxy.Director")
		},
	},
}

@golang golang locked and limited conversation to collaborators Apr 22, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants