package middleware import ( "log" "net/http" "strings" "golang.org/x/time/rate" ) func SecurityHeaders(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("X-Frame-Options", "DENY") w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin") next.ServeHTTP(w, req) }) } func NoListing(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if strings.HasSuffix(req.URL.Path, "/") { http.NotFound(w, req) return } next.ServeHTTP(w, req) }) } func WKDHeaders(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Header().Set("Content-Type", "application/octet-stream") w.Header().Set("Access-Control-Allow-Origin", "*") next.ServeHTTP(w, req) }) } // RateLimit is parameterized by the limiter instance, so each module // that needs rate limiting owns its own limiter rather than sharing // a package-level global. func RateLimit(limiter *rate.Limiter) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if !limiter.Allow() { log.Println("rate limit exceeded") w.WriteHeader(http.StatusTooManyRequests) return } next.ServeHTTP(w, req) }) } }