From 5261ef893c362ffc97e1ecb958f6e81e03cf74ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Matczuk?= Date: Tue, 8 Nov 2022 12:17:59 +0100 Subject: [PATCH 1/2] proxy: return 502 Bad Gateway on round-trip error Currently, it's not possible to distinguish target server internal error from using a wrong server or server being down. This patch changes status code 500 to 502 in case we cannot get a response from upstream. Below snippets from the HTTP specification: > The HyperText Transfer Protocol (HTTP) 502 Bad Gateway > server error response code indicates that the server, while acting as a gateway or proxy, received an invalid response from the upstream server. https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502 vs. > The HyperText Transfer Protocol (HTTP) 500 Internal Server Error > server error response code indicates that the server encountered an unexpected condition that prevented it from fulfilling the request. > This error response is a generic "catch-all" response. Usually, this indicates the server cannot find a better 5xx error code to response. Sometimes, server administrators log error responses like the 500 status code with more details about the request to prevent the error from happening again in the future. https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500 Fixes #51 --- proxy.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proxy.go b/proxy.go index fa5494c6..2ed3535b 100644 --- a/proxy.go +++ b/proxy.go @@ -172,11 +172,11 @@ func (proxy *ProxyHttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) if ctx.Error != nil { errorString = "error read response " + r.URL.Host + " : " + ctx.Error.Error() ctx.Logf(errorString) - http.Error(w, ctx.Error.Error(), 500) + http.Error(w, ctx.Error.Error(), 502) } else { errorString = "error read response " + r.URL.Host ctx.Logf(errorString) - http.Error(w, errorString, 500) + http.Error(w, errorString, 502) } return } From c670f39db8004f0d8a27d180463784ddc6baf5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Matczuk?= Date: Tue, 8 Nov 2022 16:22:11 +0100 Subject: [PATCH 2/2] proxy: improve error handling if there is no response This patch allows to distinguish between status codes * 502 - network error, failed to dial * 504 - network error, dial timeout * 500 - other error Relates to #51 --- proxy.go | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/proxy.go b/proxy.go index 2ed3535b..8cbf433a 100644 --- a/proxy.go +++ b/proxy.go @@ -168,16 +168,29 @@ func (proxy *ProxyHttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) resp = proxy.filterResponse(resp, ctx) if resp == nil { - var errorString string - if ctx.Error != nil { - errorString = "error read response " + r.URL.Host + " : " + ctx.Error.Error() - ctx.Logf(errorString) - http.Error(w, ctx.Error.Error(), 502) + var ( + errorString string + code int + ) + + if e, ok := ctx.Error.(net.Error); ok { + if e.Timeout() { + errorString = "timed out connecting to remote host: " + e.Error() + code = http.StatusGatewayTimeout + } else { + errorString = "failed to connect to remote host: " + e.Error() + code = http.StatusBadGateway + } + } else if ctx.Error != nil { + errorString = "failed to read response from remote host: " + e.Error() + code = http.StatusInternalServerError } else { - errorString = "error read response " + r.URL.Host - ctx.Logf(errorString) - http.Error(w, errorString, 502) + errorString = "failed to read response from remote host: " + r.URL.Host + code = http.StatusInternalServerError } + + ctx.Logf(errorString) + http.Error(w, errorString, code) return } ctx.Logf("Copying response to client %v [%d]", resp.Status, resp.StatusCode)