From 7ddfdc939af4257e46531f0cae0ecda93e70a9d4 Mon Sep 17 00:00:00 2001 From: Sumner Evans Date: Fri, 23 Aug 2024 14:04:29 -0600 Subject: [PATCH] exhttp: add HandleErrors which allows custom 404 and 405 errors Signed-off-by: Sumner Evans --- exhttp/handleerrors.go | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 exhttp/handleerrors.go diff --git a/exhttp/handleerrors.go b/exhttp/handleerrors.go new file mode 100644 index 0000000..d2d37b1 --- /dev/null +++ b/exhttp/handleerrors.go @@ -0,0 +1,58 @@ +package exhttp + +import "net/http" + +type ErrorBodyGenerators struct { + NotFound func() []byte + MethodNotAllowed func() []byte +} + +func HandleErrors(next http.Handler, gen ErrorBodyGenerators) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + next.ServeHTTP(&bodyOverrider{ + ResponseWriter: w, + statusNotFoundBodyGenerator: gen.NotFound, + statusMethodNotAllowedBodyGenerator: gen.MethodNotAllowed, + }, r) + }) +} + +type bodyOverrider struct { + http.ResponseWriter + + code int + override bool + + statusNotFoundBodyGenerator func() []byte + statusMethodNotAllowedBodyGenerator func() []byte +} + +var _ http.ResponseWriter = (*bodyOverrider)(nil) + +func (b *bodyOverrider) WriteHeader(code int) { + if b.Header().Get("Content-Type") == "text/plain; charset=utf-8" { + b.Header().Set("Content-Type", "application/json") + + b.override = true + } + + b.code = code + b.ResponseWriter.WriteHeader(code) +} + +func (b *bodyOverrider) Write(body []byte) (int, error) { + if b.override { + switch b.code { + case http.StatusNotFound: + if b.statusNotFoundBodyGenerator != nil { + body = b.statusNotFoundBodyGenerator() + } + case http.StatusMethodNotAllowed: + if b.statusMethodNotAllowedBodyGenerator != nil { + body = b.statusMethodNotAllowedBodyGenerator() + } + } + } + + return b.ResponseWriter.Write(body) +}