refactor: Integrate PreferencesMiddleware and update handlers
Complete middleware integration with comprehensive testing: 1. Middleware Integration - Added PreferencesMiddleware to middleware chain in routes - Order: Recovery → Logger → SecurityHeaders → Preferences → Mux - Reads all preference cookies once per request - Stores in context for handlers to access 2. Handler Updates - cv_pages.go: Home handler uses middleware.GetPreferences() - cv_htmx.go: All toggle handlers use middleware preferences - Eliminated manual cookie reading in handlers - Migration logic handled entirely by middleware 3. Comprehensive Middleware Tests - Created preferences_test.go with 10+ test functions - Tests: default values, migrations, cookie setting, context access - Verified: extended→long, true→show, false→hide migrations - All tests passing Benefits: - Performance: Cookies read once per request (not multiple times) - Consistency: All handlers get same preference values - Maintainability: Migration logic centralized in middleware - Testability: Easy to mock preferences via context Testing: - All unit tests pass (handlers + middleware) - Build succeeds - No breaking changes
This commit is contained in:
@@ -2,6 +2,8 @@ package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/juanatsap/cv-site/internal/middleware"
|
||||
)
|
||||
|
||||
// ==============================================================================
|
||||
@@ -17,13 +19,9 @@ func (h *CVHandler) ToggleLength(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get current state
|
||||
currentLength := getPreferenceCookie(r, "cv-length", "short")
|
||||
|
||||
// Migrate old value if needed
|
||||
if currentLength == "extended" {
|
||||
currentLength = "long"
|
||||
}
|
||||
// Get current preferences from context (set by middleware, already migrated)
|
||||
prefs := middleware.GetPreferences(r)
|
||||
currentLength := prefs.CVLength
|
||||
|
||||
// Toggle state
|
||||
newLength := "long"
|
||||
@@ -32,12 +30,12 @@ func (h *CVHandler) ToggleLength(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Save new state
|
||||
setPreferenceCookie(w, "cv-length", newLength)
|
||||
middleware.SetPreferenceCookie(w, "cv-length", newLength)
|
||||
|
||||
// Get language
|
||||
// Get language from query or use current preference
|
||||
lang := r.URL.Query().Get("lang")
|
||||
if lang == "" {
|
||||
lang = getPreferenceCookie(r, "cv-language", "en")
|
||||
lang = prefs.CVLanguage
|
||||
}
|
||||
|
||||
// Prepare template data with length state
|
||||
@@ -72,16 +70,9 @@ func (h *CVHandler) ToggleIcons(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get current state
|
||||
currentIcons := getPreferenceCookie(r, "cv-icons", "show")
|
||||
|
||||
// Migrate old values if needed
|
||||
switch currentIcons {
|
||||
case "true":
|
||||
currentIcons = "show"
|
||||
case "false":
|
||||
currentIcons = "hide"
|
||||
}
|
||||
// Get current preferences from context (set by middleware, already migrated)
|
||||
prefs := middleware.GetPreferences(r)
|
||||
currentIcons := prefs.CVIcons
|
||||
|
||||
// Toggle state
|
||||
newIcons := "hide"
|
||||
@@ -90,12 +81,12 @@ func (h *CVHandler) ToggleIcons(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Save new state
|
||||
setPreferenceCookie(w, "cv-icons", newIcons)
|
||||
middleware.SetPreferenceCookie(w, "cv-icons", newIcons)
|
||||
|
||||
// Get language
|
||||
// Get language from query or use current preference
|
||||
lang := r.URL.Query().Get("lang")
|
||||
if lang == "" {
|
||||
lang = getPreferenceCookie(r, "cv-language", "en")
|
||||
lang = prefs.CVLanguage
|
||||
}
|
||||
|
||||
// Prepare template data with logo state
|
||||
@@ -135,7 +126,7 @@ func (h *CVHandler) SwitchLanguage(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Save language preference
|
||||
setPreferenceCookie(w, "cv-language", lang)
|
||||
middleware.SetPreferenceCookie(w, "cv-language", lang)
|
||||
|
||||
// Prepare template data
|
||||
data, err := h.prepareTemplateData(lang)
|
||||
@@ -144,19 +135,17 @@ func (h *CVHandler) SwitchLanguage(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Preserve current length and logo preferences
|
||||
cvLength := getPreferenceCookie(r, "cv-length", "short")
|
||||
cvIcons := getPreferenceCookie(r, "cv-icons", "show")
|
||||
cvTheme := getPreferenceCookie(r, "cv-theme", "default")
|
||||
// Get current preferences from context (set by middleware)
|
||||
prefs := middleware.GetPreferences(r)
|
||||
|
||||
// Add preferences to data
|
||||
if cvLength == "long" {
|
||||
if prefs.CVLength == "long" {
|
||||
data["CVLengthClass"] = "cv-long"
|
||||
} else {
|
||||
data["CVLengthClass"] = "cv-short"
|
||||
}
|
||||
data["ShowIcons"] = (cvIcons == "show")
|
||||
data["ThemeClean"] = (cvTheme == "clean")
|
||||
data["ShowIcons"] = (prefs.CVIcons == "show")
|
||||
data["ThemeClean"] = (prefs.CVTheme == "clean")
|
||||
|
||||
// Render language-switch template with out-of-band swaps
|
||||
tmpl, err := h.templates.Render("language-switch.html")
|
||||
@@ -179,8 +168,9 @@ func (h *CVHandler) ToggleTheme(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get current state
|
||||
currentTheme := getPreferenceCookie(r, "cv-theme", "default")
|
||||
// Get current preferences from context (set by middleware)
|
||||
prefs := middleware.GetPreferences(r)
|
||||
currentTheme := prefs.CVTheme
|
||||
|
||||
// Toggle state
|
||||
newTheme := "clean"
|
||||
@@ -189,12 +179,12 @@ func (h *CVHandler) ToggleTheme(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Save new state
|
||||
setPreferenceCookie(w, "cv-theme", newTheme)
|
||||
middleware.SetPreferenceCookie(w, "cv-theme", newTheme)
|
||||
|
||||
// Get language
|
||||
// Get language from query or use current preference
|
||||
lang := r.URL.Query().Get("lang")
|
||||
if lang == "" {
|
||||
lang = getPreferenceCookie(r, "cv-language", "en")
|
||||
lang = prefs.CVLanguage
|
||||
}
|
||||
|
||||
// Prepare template data with theme state
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/juanatsap/cv-site/internal/middleware"
|
||||
"github.com/juanatsap/cv-site/internal/pdf"
|
||||
)
|
||||
|
||||
@@ -43,26 +44,13 @@ func (h *CVHandler) Home(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get user preferences from context (set by middleware)
|
||||
// Note: Middleware should be enabled in routes for this to work
|
||||
// For now, fall back to direct cookie reading for backward compatibility
|
||||
cvLength := getPreferenceCookie(r, "cv-length", "short")
|
||||
cvIcons := getPreferenceCookie(r, "cv-icons", "show")
|
||||
cvTheme := getPreferenceCookie(r, "cv-theme", "default")
|
||||
// Get user preferences from context (set by PreferencesMiddleware)
|
||||
prefs := middleware.GetPreferences(r)
|
||||
|
||||
// Migrate old preference values to new ones (one-time auto-migration)
|
||||
if cvLength == "extended" {
|
||||
cvLength = "long"
|
||||
setPreferenceCookie(w, "cv-length", "long")
|
||||
}
|
||||
switch cvIcons {
|
||||
case "true":
|
||||
cvIcons = "show"
|
||||
setPreferenceCookie(w, "cv-icons", "show")
|
||||
case "false":
|
||||
cvIcons = "hide"
|
||||
setPreferenceCookie(w, "cv-icons", "hide")
|
||||
}
|
||||
// Use preferences from context (already migrated by middleware)
|
||||
cvLength := prefs.CVLength
|
||||
cvIcons := prefs.CVIcons
|
||||
cvTheme := prefs.CVTheme
|
||||
|
||||
// Add preference-specific fields to template data
|
||||
cvLengthClass := "cv-short"
|
||||
|
||||
Reference in New Issue
Block a user