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: ReverseProxy should allow for the upstream errors to be customized #12605

Closed
mdp opened this issue Sep 13, 2015 · 12 comments
Closed

Comments

@mdp
Copy link

mdp commented Sep 13, 2015

Currently when the Transport of a ReverseProxy returns an error (such as from a bad upstream gateway) we return a StatusInternalServerError to the end user and close the client request See reverse_proxy.go#L194. It would be nice if this were easily customizable.

One option would be the let the developer specify an error handler function and handle the client connection themselves. This would also resolve #9864.

Something as simple as the following may be enough:
0b5bcf5...mdp:proxy_error

Ideas? Another option would be to just have the developer write their own Transport and handle the error inside of that.

@ianlancetaylor ianlancetaylor changed the title ReverseProxy should allow for the upstream errors to be customized net/http/httputil: ReverseProxy should allow for the upstream errors to be customized Sep 14, 2015
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Sep 14, 2015
@ianlancetaylor
Copy link
Contributor

CC @bradfitz

@mitch000001
Copy link

@mdp To not break existing programs I would suggest to return the same header as before when no error handler is provided.

@mdp
Copy link
Author

mdp commented Sep 14, 2015

@mitch000001 Yeah, good point. I was trying to align this with #9864, which was marked a "go1.5maybe" and wanted to match it's return BadGateway(502), but it's probably better to keep that as a separate issue. Fixed in my proposed solution.

@bradfitz
Copy link
Contributor

Want to send a change?
https://golang.org/doc/contribute.html

@mdp
Copy link
Author

mdp commented Nov 12, 2015

@gopherbot
Copy link

CL https://golang.org/cl/16839 mentions this issue.

@bmizerany
Copy link
Contributor

This can also be solved without changing ReverseProxy:

type errorHandlingRoundTripper struct {
        tr http.RoundTripper
}

func (rt *errorHandlingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
        tr := errorHandlingRoundTripper.tr
        if tr == nil {
                tr = http.DefaultTransport
        }
        res, err := rt.tr.RoundTrip(req)
        if isBadGateway(err) {
                return &http.Response{
                        StatusCode: StatusBadGateway,
                        // more stuff
                }, nil
        }
        return res, err
}

And use like:

rt := &httputil.RoundTripper{Transport: errorHandlingRoundTripper{}}

@mdp
Copy link
Author

mdp commented Nov 13, 2015

Yeah, I mentioned this option at the end of opening issue. As you've shown, it's a trivial amount of code to implement without modifying ReverseProxy.

My arguments for:

  • Having the TransportErrorHandler makes it clear in the docs how to handle errors.
  • It's a fairly common use case to catch upstream errors and handle them with custom logic for downstream clients, so having a simple handler would make it clear to the developer that it's something they should probably handle.
  • It doesn't break existing implementations.

But like you've shown, it's easy to work around without any modification to ReverseProxy. I'm happy to close the issue if that's what's determined. Thanks

@nightlyone
Copy link
Contributor

I would prefer a customized transport for that in order to minimize API and keep "tuning knobs" away.

But if it is really common to do that, I would suggest to add the code from @bmizerany as an example to the package.

@mdp
Copy link
Author

mdp commented Nov 13, 2015

I might be the exception here, but if I'm building a reverse proxy I will always want to handle the error with a custom function rather than a blank response and a 500. For me it's less of a "tuning knob" and more of something that I will always have to implement as a custom transport.

But if I'm the exception then I agree, it's definitely an unnecessary addition to the API.

@bmizerany Thoughts? If we don't want to change ReverseProxy I think your example code would still be a nice addition to the documentation as @nightlyone suggested

@bmizerany
Copy link
Contributor

I don't want to add something to the public API if there is a clean alternative already in existence, but that isn't my decision. I defer to @bradfitz and gang for more thoughts.

@bradfitz
Copy link
Contributor

bradfitz commented Dec 1, 2015

Given Blake and Ingo's points that this can be done already without changes, and given that we're trying to wind down work on the standard library, I think we'll pass on this change.

Somebody should probably fork this whole package and go nuts with it on github.

@bradfitz bradfitz closed this as completed Dec 1, 2015
@golang golang locked and limited conversation to collaborators Dec 1, 2016
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

7 participants