Files
at-container-registry/pkg/appview/handlers/errors.go
T

71 lines
1.9 KiB
Go

package handlers
import (
"encoding/json"
"log/slog"
"net/http"
)
// NotFoundHandler handles 404 errors
type NotFoundHandler struct {
BaseUIHandler
}
func (h *NotFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
RenderNotFound(w, r, &h.BaseUIHandler)
}
// RenderNotFound renders the 404 page template.
// Use this from other handlers when a resource is not found.
func RenderNotFound(w http.ResponseWriter, r *http.Request, h *BaseUIHandler) {
w.WriteHeader(http.StatusNotFound)
meta := NewPageMeta(
"404 - Lost at Sea | "+h.ClientShortName,
"Page not found - the requested resource doesn't exist on "+h.ClientShortName,
).WithRobots("noindex").
WithSiteName(h.ClientShortName)
data := struct {
PageData
Meta *PageMeta
}{
PageData: NewPageData(r, h),
Meta: meta,
}
if err := h.Templates.ExecuteTemplate(w, "404", data); err != nil {
http.Error(w, "Page not found", http.StatusNotFound)
}
}
// RenderHTMXError sends an error response suitable for htmx. For htmx requests
// it sets an HX-Trigger header so the client fires a toast event; the JS
// fallback in app.js will show a generic toast even without the header.
// For non-htmx requests it falls back to http.Error. serverErr is logged but
// never exposed to the user — pass userMsg for anything screen-readable.
func RenderHTMXError(w http.ResponseWriter, r *http.Request, status int, userMsg string, serverErr error) {
if serverErr != nil {
slog.Error("htmx handler error",
"path", r.URL.Path,
"status", status,
"err", serverErr,
)
}
if userMsg == "" {
userMsg = http.StatusText(status)
}
if r.Header.Get("HX-Request") == "true" {
trigger := map[string]map[string]string{
"toast": {"message": userMsg, "type": "error"},
}
if b, err := json.Marshal(trigger); err == nil {
w.Header().Set("HX-Trigger", string(b))
}
w.Header().Set("HX-Reswap", "none")
w.WriteHeader(status)
return
}
http.Error(w, userMsg, status)
}