lookbook/internal/handlers/handler.go
soup cdcc5b5293
Initial commit: Lookbook personal collection app
Pinterest-like app for saving images, videos, quotes, and embeds.

Features:
- Go backend with PostgreSQL, SSR templates
- Console-based admin auth (login/logout via browser console)
- Item types: images, videos (ffmpeg transcoding), quotes, embeds
- Media stored as BLOBs in PostgreSQL
- OpenGraph metadata extraction for links
- Embed detection for YouTube, Vimeo, Twitter/X
- Masonry grid layout, item detail pages
- Tag system with filtering
- Refresh metadata endpoint with change warnings
- Replace media endpoint for updating item images/videos
2026-01-17 01:09:23 -05:00

49 lines
1.2 KiB
Go

package handlers
import (
"log/slog"
"net/http"
)
// Handler is a function that handles HTTP requests and can return an error.
// It receives a RequestContext with injected dependencies (DB, Logger).
type Handler func(rc *RequestContext, w http.ResponseWriter, r *http.Request) error
// WithErrorHandling wraps a Handler to automatically handle errors.
func WithErrorHandling(rc *RequestContext, h Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
wrapper := &responseWrapper{
ResponseWriter: w,
written: false,
}
err := h(rc, wrapper, r)
if err != nil {
rc.Logger.Error("handler error",
slog.String("method", r.Method),
slog.String("path", r.URL.Path),
slog.Any("error", err),
)
if !wrapper.written {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}
}
}
// responseWrapper tracks if response was written
type responseWrapper struct {
http.ResponseWriter
written bool
}
func (w *responseWrapper) Write(b []byte) (int, error) {
w.written = true
return w.ResponseWriter.Write(b)
}
func (w *responseWrapper) WriteHeader(statusCode int) {
w.written = true
w.ResponseWriter.WriteHeader(statusCode)
}