From 47c570855fa54ddfcf4a11ceae1c2312130d63e2 Mon Sep 17 00:00:00 2001 From: "Gustavo L de Mello (Guz)" Date: Mon, 7 Oct 2024 15:40:26 -0300 Subject: [PATCH] feat(router): error handling of routes --- router/rerrors/400s.go | 16 +++++++++++ router/rerrors/500s.go | 12 +++++++++ router/rerrors/errors.go | 57 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 router/rerrors/400s.go create mode 100644 router/rerrors/500s.go create mode 100644 router/rerrors/errors.go diff --git a/router/rerrors/400s.go b/router/rerrors/400s.go new file mode 100644 index 0000000..3f9be6c --- /dev/null +++ b/router/rerrors/400s.go @@ -0,0 +1,16 @@ +package rerrors + +import "net/http" + +func MissingParameters(params []string) RouteError { + return NewRouteError(http.StatusBadRequest, "Missing parameters", map[string]any{ + "missing_parameters": params, + }) +} + +func MethodNowAllowed(method string, allowedMethods []string) RouteError { + return NewRouteError(http.StatusMethodNotAllowed, "Method not allowed", map[string]any{ + "method": method, + "allowed_methods": allowedMethods, + }) +} diff --git a/router/rerrors/500s.go b/router/rerrors/500s.go new file mode 100644 index 0000000..36089ad --- /dev/null +++ b/router/rerrors/500s.go @@ -0,0 +1,12 @@ +package rerrors + +import ( + "errors" + "net/http" +) + +func InternalError(errs ...error) RouteError { + return NewRouteError(http.StatusInternalServerError, "Internal server error", map[string]any{ + "errors": errors.Join(errs...), + }) +} diff --git a/router/rerrors/errors.go b/router/rerrors/errors.go new file mode 100644 index 0000000..9a2d4c3 --- /dev/null +++ b/router/rerrors/errors.go @@ -0,0 +1,57 @@ +package rerrors + +import ( + "encoding/json" + "fmt" + "net/http" +) + +type RouteError struct { + StatusCode int `json:"status_code"` + Error string `json:"error"` + Info map[string]any `json:"info"` +} + +func NewRouteError(status int, error string, info ...map[string]any) RouteError { + rerr := RouteError{StatusCode: status, Error: error} + if len(info) > 0 { + rerr.Info = info[0] + } else { + rerr.Info = map[string]any{} + } + return rerr +} + +func (rerr RouteError) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if rerr.StatusCode == 0 { + rerr.StatusCode = http.StatusNotImplemented + } + + if rerr.Error == "" { + rerr.Error = "MISSING ERROR DESCRIPTION" + } + + if rerr.Info == nil { + rerr.Info = map[string]any{} + } + + w.Header().Set("Content-Type", "application/json") + + j, err := json.Marshal(rerr) + if err != nil { + j, _ := json.Marshal(RouteError{ + StatusCode: http.StatusInternalServerError, + Error: "Failed to marshal error message to JSON", + Info: map[string]any{ + "source_value": fmt.Sprintf("%#v", rerr), + "error": err.Error(), + }, + }) + w.Write(j) + w.WriteHeader(http.StatusInternalServerError) + return + } + + w.Write(j) + w.WriteHeader(rerr.StatusCode) +}