hakobox/routes/middleware.go
2025-04-21 17:59:57 -03:00

97 lines
2 KiB
Go

package routes
import (
"context"
"errors"
"fmt"
"foobar/views"
"net/http"
"github.com/a-h/templ"
)
type userError struct {
error
user string
}
type redirectURL string
type postRouteRedirectFunc func(http.ResponseWriter, *http.Request) (redirectURL, error)
type routeGetFunc func(http.ResponseWriter, *http.Request) (templ.Component, error)
var (
errUser = errors.New("user error")
)
func newUserError(msg string) *userError {
return &userError{
user: msg,
}
}
func (u *userError) Error() string {
return u.user
}
func (u redirectURL) Valid() bool {
return len(u) > 0 && u[0] == '/'
}
func getRouteMiddleware(fun routeGetFunc) http.HandlerFunc {
// TODO: handle boosted HTMX requests gracefully
return func(w http.ResponseWriter, r *http.Request) {
component, err := fun(w, r)
if err != nil {
logInternalError(w, err)
return
}
err = component.Render(context.Background(), w)
if err != nil {
logInternalError(w, err)
return
}
}
}
func redirectHtmxFormMiddleware(fun postRouteRedirectFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
hxRequest := r.Header.Get("HX-Request") == "true"
redirectURL, err := fun(w, r)
if err != nil {
w.Header().Add("HX-Retarget", "#error-target")
w.Header().Add("HX-Reswap", "innerHTML")
w.WriteHeader(http.StatusUnprocessableEntity)
if u, ok := err.(*userError); ok {
if hxRequest {
err = views.ErrorBox(u.user).Render(context.Background(), w)
if err != nil {
logError(fmt.Errorf("%w: %s", err, r.URL.Path))
}
} else {
_, _ = w.Write([]byte(u.user))
}
return
} else {
msg := "Internal error... See the server logs for more information"
_ = views.ErrorBox(msg).Render(context.Background(), w)
logError(err)
return
}
}
if !redirectURL.Valid() {
panic("not implemented")
}
if hxRequest {
w.Header().Add("HX-Redirect", string(redirectURL))
} else {
http.Redirect(w, r, string(redirectURL), http.StatusFound)
}
}
}