aboutsummaryrefslogtreecommitdiff
path: root/src/net/http/httputil/reverseproxy.go
diff options
context:
space:
mode:
authorJulien Salleyron <julien.salleyron@gmail.com>2017-11-13 23:32:07 +0100
committerBrad Fitzpatrick <bradfitz@golang.org>2018-07-13 16:45:34 +0000
commit5201b1ad225e7503e368386ae3ad4f94d7b04d8b (patch)
tree0a3378db078c45481c82404171ab355163a5e8d2 /src/net/http/httputil/reverseproxy.go
parent86a0e67a03370601956133119982167ffadd526d (diff)
downloadgo-5201b1ad225e7503e368386ae3ad4f94d7b04d8b.tar.xz
http/http/httputil: add ReverseProxy.ErrorHandler
This permits specifying an ErrorHandler to customize the RoundTrip error handling if the backend fails to return a response. Fixes #22700 Fixes #21255 Change-Id: I8879f0956e2472a07f584660afa10105ef23bf11 Reviewed-on: https://go-review.googlesource.com/77410 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/net/http/httputil/reverseproxy.go')
-rw-r--r--src/net/http/httputil/reverseproxy.go37
1 files changed, 30 insertions, 7 deletions
diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
index 6f0a2418b3..1dddaa95a7 100644
--- a/src/net/http/httputil/reverseproxy.go
+++ b/src/net/http/httputil/reverseproxy.go
@@ -55,10 +55,23 @@ type ReverseProxy struct {
// copying HTTP response bodies.
BufferPool BufferPool
- // ModifyResponse is an optional function that
- // modifies the Response from the backend.
- // If it returns an error, the proxy returns a StatusBadGateway error.
+ // ModifyResponse is an optional function that modifies the
+ // Response from the backend. It is called if the backend
+ // returns a response at all, with any HTTP status code.
+ // If the backend is unreachable, the optional ErrorHandler is
+ // called without any call to ModifyResponse.
+ //
+ // If ModifyResponse returns an error, ErrorHandler is called
+ // with its error value. If ErrorHandler is nil, its default
+ // implementation is used.
ModifyResponse func(*http.Response) error
+
+ // ErrorHandler is an optional function that handles errors
+ // reaching the backend or errors from ModifyResponse.
+ //
+ // If nil, the default is to log the provided error and return
+ // a 502 Status Bad Gateway response.
+ ErrorHandler func(http.ResponseWriter, *http.Request, error)
}
// A BufferPool is an interface for getting and returning temporary
@@ -141,6 +154,18 @@ var hopHeaders = []string{
"Upgrade",
}
+func (p *ReverseProxy) defaultErrorHandler(rw http.ResponseWriter, req *http.Request, err error) {
+ p.logf("http: proxy error: %v", err)
+ rw.WriteHeader(http.StatusBadGateway)
+}
+
+func (p *ReverseProxy) getErrorHandler() func(http.ResponseWriter, *http.Request, error) {
+ if p.ErrorHandler != nil {
+ return p.ErrorHandler
+ }
+ return p.defaultErrorHandler
+}
+
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
transport := p.Transport
if transport == nil {
@@ -206,8 +231,7 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
res, err := transport.RoundTrip(outreq)
if err != nil {
- p.logf("http: proxy error: %v", err)
- rw.WriteHeader(http.StatusBadGateway)
+ p.getErrorHandler()(rw, outreq, err)
return
}
@@ -219,9 +243,8 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if p.ModifyResponse != nil {
if err := p.ModifyResponse(res); err != nil {
- p.logf("http: proxy error: %v", err)
- rw.WriteHeader(http.StatusBadGateway)
res.Body.Close()
+ p.getErrorHandler()(rw, outreq, err)
return
}
}