lure-web/error.go

91 lines
1.8 KiB
Go

package main
import (
"database/sql"
"errors"
"net/http"
"github.com/uptrace/bunrouter"
"go.elara.ws/logger/log"
"go.elara.ws/salix"
)
type HTTPError struct {
StatusCode int `json:"status_code"`
Msg string `json:"error"`
}
func (he HTTPError) Error() string {
return he.Msg
}
func (he HTTPError) StatusText() string {
return http.StatusText(he.StatusCode)
}
func httpError(err error) *HTTPError {
switch err := err.(type) {
case nil:
return nil
case HTTPError:
return &err
case *HTTPError:
return err
default:
switch {
case errors.Is(err, sql.ErrNoRows):
return &HTTPError{404, err.Error()}
default:
return &HTTPError{500, err.Error()}
}
}
}
func siteErrorHandler(ns *salix.Namespace) bunrouter.MiddlewareFunc {
return func(next bunrouter.HandlerFunc) bunrouter.HandlerFunc {
tmpl, ok := ns.GetTemplate("error.html")
if !ok {
return basicErrorHandler(next)
}
return func(w http.ResponseWriter, req bunrouter.Request) error {
err := next(w, req)
if err != nil {
he := httpError(err)
w.WriteHeader(he.StatusCode)
err := tmpl.
WithVarMap(map[string]any{"error": he}).
Execute(w)
if err != nil {
log.Error("Error while executing error template").Err(err).Send()
}
}
return err
}
}
}
func apiErrorHandler(next bunrouter.HandlerFunc) bunrouter.HandlerFunc {
return func(w http.ResponseWriter, req bunrouter.Request) error {
err := next(w, req)
if err != nil {
he := httpError(err)
w.WriteHeader(he.StatusCode)
_ = bunrouter.JSON(w, map[string]string{"error": he.Msg})
}
return err
}
}
func basicErrorHandler(next bunrouter.HandlerFunc) bunrouter.HandlerFunc {
return func(w http.ResponseWriter, req bunrouter.Request) error {
err := next(w, req)
if err != nil {
he := httpError(err)
http.Error(w, he.Msg, he.StatusCode)
}
return err
}
}