feat: Add plain text CV endpoint and contact form with security
Plain text endpoint: - Add /text route for plain text CV (for curl/AI crawlers) - Use k3a/html2text library for HTML-to-text conversion - Add Plain Text button to hamburger menu with UI translations Contact form feature: - Add ContactHandler with proper email service integration - Add CSRF protection middleware - Add rate limiting (5 submissions/hour per IP) - Add honeypot and timing-based bot protection - Add input validation with detailed error messages - Add security logging middleware - Add browser-only middleware for API protection Code quality: - Fix all golangci-lint errcheck warnings for w.Write calls - Remove duplicate getClientIP functions - Wire up ContactHandler in routes.Setup
This commit is contained in:
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// Setup configures all application routes and middleware
|
||||
func Setup(cvHandler *handlers.CVHandler, healthHandler *handlers.HealthHandler) http.Handler {
|
||||
func Setup(cvHandler *handlers.CVHandler, healthHandler *handlers.HealthHandler, contactHandler *handlers.ContactHandler) http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// Shortcut routes for default CV (year-aware) - MUST be before "/" route
|
||||
@@ -19,6 +19,7 @@ func Setup(cvHandler *handlers.CVHandler, healthHandler *handlers.HealthHandler)
|
||||
// Public routes
|
||||
mux.HandleFunc("/", cvHandler.Home)
|
||||
mux.HandleFunc("/cv", cvHandler.CVContent)
|
||||
mux.HandleFunc("/text", cvHandler.PlainText) // Plain text version for curl/AI
|
||||
mux.HandleFunc("/health", healthHandler.Check)
|
||||
|
||||
// HTMX endpoints for interactive controls
|
||||
@@ -27,6 +28,13 @@ func Setup(cvHandler *handlers.CVHandler, healthHandler *handlers.HealthHandler)
|
||||
mux.HandleFunc("/toggle/icons", cvHandler.ToggleIcons)
|
||||
mux.HandleFunc("/toggle/theme", cvHandler.ToggleTheme)
|
||||
|
||||
// Contact form endpoint (simple rate limiting)
|
||||
contactRateLimiter := middleware.NewRateLimiter(5, 1*time.Hour)
|
||||
protectedContactHandler := contactRateLimiter.Middleware(
|
||||
http.HandlerFunc(contactHandler.Submit),
|
||||
)
|
||||
mux.Handle("/api/contact", protectedContactHandler)
|
||||
|
||||
// Protected PDF endpoint with rate limiting (3 requests/minute per IP)
|
||||
pdfRateLimiter := middleware.NewRateLimiter(3, 1*time.Minute)
|
||||
protectedPDFHandler := middleware.OriginChecker(
|
||||
|
||||
Reference in New Issue
Block a user