goshort/internal/server/errors.go

99 lines
2.5 KiB
Go
Raw Permalink Normal View History

2023-08-17 14:14:59 -03:00
package server
import (
"net/http"
"github.com/go-chi/render"
)
// ErrResponse renderer type for handling all sorts of errors.
//
// In the best case scenario, the excellent github.com/pkg/errors package
// helps reveal information on the error, setting it on Err, and in the Render()
// method, using it to set the application-specific error code in AppCode.
type ErrResponse struct {
Err error `json:"-"` // low-level runtime error
HTTPStatusCode int `json:"-"` // http response status code
StatusText string `json:"status"` // user-level status message
ErrorText string `json:"error,omitempty"` // application-level error message, for debugging
}
2023-08-26 11:47:46 -03:00
func (e *ErrResponse) Render(_ http.ResponseWriter, r *http.Request) error {
2023-08-17 14:14:59 -03:00
render.Status(r, e.HTTPStatusCode)
2023-08-26 11:47:46 -03:00
2023-08-17 14:14:59 -03:00
return nil
}
2023-08-21 18:08:41 -03:00
func ErrBasic(status int) *ErrResponse {
2023-08-17 14:14:59 -03:00
return &ErrResponse{
HTTPStatusCode: status,
StatusText: http.StatusText(status),
}
}
2023-08-26 11:47:46 -03:00
func ErrGeneric(err error, status int) *ErrResponse {
2023-08-21 18:08:41 -03:00
resp := ErrBasic(status)
resp.Err = err
resp.ErrorText = err.Error()
2023-08-26 11:47:46 -03:00
2023-08-21 18:08:41 -03:00
return resp
}
2023-08-26 11:47:46 -03:00
func ErrBadRequest(err error) *ErrResponse {
2023-08-17 14:14:59 -03:00
return ErrGeneric(err, http.StatusBadRequest)
}
2023-08-26 11:47:46 -03:00
func ErrNotFound() *ErrResponse {
2023-08-21 18:08:41 -03:00
return ErrBasic(http.StatusNotFound)
2023-08-17 14:14:59 -03:00
}
2023-08-26 11:47:46 -03:00
func ErrUnauthorized() *ErrResponse {
2023-08-21 18:08:41 -03:00
return ErrBasic(http.StatusUnauthorized)
2023-08-17 17:55:28 -03:00
}
2023-08-26 11:47:46 -03:00
func ErrForbidden() *ErrResponse {
2023-08-21 18:08:41 -03:00
return ErrBasic(http.StatusForbidden)
2023-08-17 17:55:28 -03:00
}
2023-08-26 11:47:46 -03:00
func ErrRendering(err error) *ErrResponse {
2023-08-17 14:14:59 -03:00
return &ErrResponse{
Err: err,
2023-08-26 11:47:46 -03:00
HTTPStatusCode: http.StatusUnprocessableEntity,
2023-08-17 14:14:59 -03:00
StatusText: "Error rendering response.",
ErrorText: err.Error(),
}
}
func RenderRender(w http.ResponseWriter, r *http.Request, resp render.Renderer) {
// Try to render the response
if err := render.Render(w, r, resp); err != nil {
2023-08-26 11:47:46 -03:00
// If error, try to render that an error occurred
2023-08-17 14:14:59 -03:00
if err := render.Render(w, r, ErrRendering(err)); err != nil {
// If error, panic
panic(err)
}
}
}
2023-08-21 01:19:10 -03:00
func RenderBadRequest(w http.ResponseWriter, r *http.Request, err error) {
RenderRender(w, r, ErrBadRequest(err))
}
2023-08-26 11:47:46 -03:00
func RenderServerError(_ http.ResponseWriter, _ *http.Request, err error) {
2023-08-24 22:03:58 -03:00
// Panic so the stack trace is printed
panic(err)
2023-08-21 01:19:10 -03:00
}
2023-08-21 18:08:41 -03:00
func RenderNotFound(w http.ResponseWriter, r *http.Request) {
RenderRender(w, r, ErrNotFound())
2023-08-21 01:19:10 -03:00
}
2023-08-21 18:08:41 -03:00
func RenderUnauthorized(w http.ResponseWriter, r *http.Request) {
RenderRender(w, r, ErrUnauthorized())
2023-08-21 01:19:10 -03:00
}
2023-08-21 18:08:41 -03:00
func RenderForbidden(w http.ResponseWriter, r *http.Request) {
RenderRender(w, r, ErrForbidden())
2023-08-21 01:19:10 -03:00
}