Echo errors, middleware and handlers used three different formats (message object, error object, bare string). One error handler now writes all of them the same way; status codes are unchanged.
48 lines
1.1 KiB
Go
48 lines
1.1 KiB
Go
package server
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
|
|
"music-server/internal/logging"
|
|
|
|
"github.com/labstack/echo/v5"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// ErrorResponse is the body of every error response.
|
|
type ErrorResponse struct {
|
|
Error string `json:"error" example:"Not Found"`
|
|
}
|
|
|
|
// httpErrorHandler writes every error as an ErrorResponse.
|
|
func httpErrorHandler(c *echo.Context, err error) {
|
|
if r, _ := echo.UnwrapResponse(c.Response()); r != nil && r.Committed {
|
|
return
|
|
}
|
|
|
|
code := http.StatusInternalServerError
|
|
message := http.StatusText(code)
|
|
var he *echo.HTTPError
|
|
var sc echo.HTTPStatusCoder
|
|
switch {
|
|
case errors.As(err, &he):
|
|
code = he.Code
|
|
message = he.Message
|
|
case errors.As(err, &sc):
|
|
code = sc.StatusCode()
|
|
}
|
|
if code >= http.StatusInternalServerError && he == nil {
|
|
logging.GetLogger().Error("Unhandled error", zap.String("path", c.Request().URL.Path), zap.Error(err))
|
|
}
|
|
if message == "" {
|
|
message = http.StatusText(code)
|
|
}
|
|
|
|
if c.Request().Method == http.MethodHead {
|
|
_ = c.NoContent(code)
|
|
return
|
|
}
|
|
_ = c.JSON(code, ErrorResponse{Error: message})
|
|
}
|