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
This commit is contained in:
commit
cdcc5b5293
45 changed files with 4634 additions and 0 deletions
49
internal/handlers/handler.go
Normal file
49
internal/handlers/handler.go
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
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)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue