refactor: centralize constants and reorganize documentation

- Create internal/constants package with all hardcoded values
  (environment, cookies, themes, headers, routes, cache)
- Create internal/httputil package for HTTP helper functions
- Update all handlers and middleware to use centralized constants
- Reorganize documentation with numbered prefixes (00-26)
- Remove duplicate docs from validation folder and docs/
- Delete handlers/constants.go (moved to internal/constants)
This commit is contained in:
juanatsap
2025-12-06 16:27:12 +00:00
parent 71d9258c58
commit 2c7f8de242
37 changed files with 732 additions and 343 deletions
+8 -6
View File
@@ -4,6 +4,8 @@ import (
"log"
"net/http"
"strings"
"github.com/juanatsap/cv-site/internal/constants"
)
const (
@@ -21,7 +23,7 @@ const (
func BrowserOnly(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Check 1: User-Agent validation
userAgent := r.Header.Get("User-Agent")
userAgent := r.Header.Get(constants.HeaderUserAgent)
if userAgent == "" || isBotUserAgent(userAgent) {
log.Printf("SECURITY: Blocked non-browser User-Agent from IP %s: %s", getRequestIP(r), userAgent)
http.Error(w, "Forbidden: Browser access only", http.StatusForbidden)
@@ -29,8 +31,8 @@ func BrowserOnly(next http.Handler) http.Handler {
}
// Check 2: Require Referer or Origin header
referer := r.Header.Get("Referer")
origin := r.Header.Get("Origin")
referer := r.Header.Get(constants.HeaderReferer)
origin := r.Header.Get(constants.HeaderOrigin)
if referer == "" && origin == "" {
log.Printf("SECURITY: Blocked request without Referer/Origin from IP %s", getRequestIP(r))
@@ -41,7 +43,7 @@ func BrowserOnly(next http.Handler) http.Handler {
// Check 3: Custom header validation (set by JavaScript)
// For HTMX requests, check HX-Request header
// For fetch/XMLHttpRequest, check X-Requested-With header
hasHTMXHeader := r.Header.Get("HX-Request") == "true"
hasHTMXHeader := r.Header.Get(constants.HeaderHXRequest) == "true"
hasXMLHTTPHeader := r.Header.Get(browserHeaderName) == browserHeaderValue
hasCustomBrowserHeader := r.Header.Get("X-Browser-Request") == "true"
@@ -96,7 +98,7 @@ func isBotUserAgent(ua string) bool {
// getRequestIP extracts the client IP from the request
func getRequestIP(r *http.Request) string {
// Try X-Forwarded-For first (for proxies/load balancers)
ip := r.Header.Get("X-Forwarded-For")
ip := r.Header.Get(constants.HeaderXForwardedFor)
if ip != "" {
// Take first IP if multiple
ips := strings.Split(ip, ",")
@@ -104,7 +106,7 @@ func getRequestIP(r *http.Request) string {
}
// Try X-Real-IP
ip = r.Header.Get("X-Real-IP")
ip = r.Header.Get(constants.HeaderXRealIP)
if ip != "" {
return ip
}