diff options
author | Robin Lambertz <github@roblab.la> | 2020-02-20 23:00:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-20 15:00:30 -0700 |
commit | e3591009dc8cf386704f8671c54b0f97c3f75b8c (patch) | |
tree | a85939db46988e8bbeb2ff3d82a7e932a6ea65ef | |
parent | 30c14084abda8565215972fdffc5bbc41708b32b (diff) |
caddyhttp: Add handler for unhandled errors in errorChain (#3063)
* Add handler for unhandled errors in errorChain
Currently, when an error chain is defined, the default error handler is
bypassed entirely - even if the error chain doesn't handle every error.
This results in pages returning a blank 200 OK page.
For instance, it's possible for an error chain to match on the error
status code and only handle a certain subtype of errors (like 403s). In
this case, we'd want any other errors to still go through the default
handler and return an empty page with the status code.
This PR changes the "suffix handler" passed to errorChain.Compile to
set the status code of the response to the error status code.
Fixes #3053
* Move the errorHandlerChain middleware to variable
* Style fix
-rw-r--r-- | modules/caddyhttp/caddyhttp.go | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/modules/caddyhttp/caddyhttp.go b/modules/caddyhttp/caddyhttp.go index 24121c1..30c2f79 100644 --- a/modules/caddyhttp/caddyhttp.go +++ b/modules/caddyhttp/caddyhttp.go @@ -185,7 +185,8 @@ func (app *App) Provision(ctx caddy.Context) error { if err != nil { return fmt.Errorf("server %s: setting up server error handling routes: %v", srvName, err) } - srv.errorHandlerChain = srv.Errors.Routes.Compile(emptyHandler) + + srv.errorHandlerChain = srv.Errors.Routes.Compile(errorEmptyHandler) } } @@ -413,6 +414,20 @@ type MiddlewareHandler interface { // emptyHandler is used as a no-op handler. var emptyHandler Handler = HandlerFunc(func(http.ResponseWriter, *http.Request) error { return nil }) +// An implicit suffix middleware that, if reached, sets the StatusCode to the +// error stored in the ErrorCtxKey. This is to prevent situations where the +// Error chain does not actually handle the error (for instance, it matches only +// on some errors). See #3053 +var errorEmptyHandler Handler = HandlerFunc(func(w http.ResponseWriter, r *http.Request) error { + httpError := r.Context().Value(ErrorCtxKey) + if handlerError, ok := httpError.(HandlerError); ok { + w.WriteHeader(handlerError.StatusCode) + } else { + w.WriteHeader(http.StatusInternalServerError) + } + return nil +}) + // WeakString is a type that unmarshals any JSON value // as a string literal, with the following exceptions: // |