Skip to content

Commit

Permalink
Handle context canceled errors + better http proxy error handling (#644)
Browse files Browse the repository at this point in the history
  • Loading branch information
danlsgiga authored and Aaron Hurt committed Dec 5, 2019
1 parent a6e750f commit 9c6c64a
Showing 1 changed file with 37 additions and 0 deletions.
37 changes: 37 additions & 0 deletions proxy/http_handler.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package proxy

import (
"context"
"io"
"log"
"net"
"net/http"
"net/http/httputil"
"net/url"
"time"
)

// StatusClientClosedRequest non-standard HTTP status code for client disconnection
const StatusClientClosedRequest = 499

func newHTTPProxy(target *url.URL, tr http.RoundTripper, flush time.Duration) http.Handler {
return &httputil.ReverseProxy{
// this is a simplified director function based on the
Expand All @@ -25,5 +32,35 @@ func newHTTPProxy(target *url.URL, tr http.RoundTripper, flush time.Duration) ht
},
FlushInterval: flush,
Transport: tr,
ErrorHandler: httpProxyErrorHandler,
}
}

func httpProxyErrorHandler(w http.ResponseWriter, r *http.Request, err error) {
// According to https://golang.org/src/net/http/httputil/reverseproxy.go#L74, Go will return a 502 (Bad Gateway) StatusCode by default if no ErroHandler is provided
// If a "context canceled" error is returned by the http.Request handler this means the client closed the connection before getting a response
// So we are changing the StatusCode on these situations to the non-standard 499 (Client Closed Request)

statusCode := http.StatusInternalServerError

if e, ok := err.(net.Error); ok {
if e.Timeout() {
statusCode = http.StatusGatewayTimeout
} else {
statusCode = http.StatusBadGateway
}
} else if err == io.EOF {
statusCode = http.StatusBadGateway
} else if err == context.Canceled {
statusCode = StatusClientClosedRequest
}

w.WriteHeader(statusCode)
// Theres nothing we can do if the client closes the connection and logging the "context canceled" errors will just add noise to the error log
// Note: The access_log will still log the 499 response status codes
if statusCode != StatusClientClosedRequest {
log.Print("[ERROR] ", err)
}

return
}

2 comments on commit 9c6c64a

@analytically
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be good to have a release with this change :-)

@aaronhurt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be a bit on the releases. Please see #735

Please sign in to comment.