package auth import ( "context" "net/http" "net/http/httptest" "testing" "time" ) // BenchmarkAuthMiddleware benchmarks the authentication middleware overhead. func BenchmarkAuthMiddleware(b *testing.B) { // Create a mock API key apiKey := &APIKey{ ID: "test-key-id", Name: "benchmark-key", KeyPrefix: "rdev", Scopes: []Scope{ScopeProjectsExecute, ScopeProjectsRead}, CreatedAt: time.Now(), } // Simple handler that just writes OK handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) // Wrap with a mock middleware that simulates auth without DB middleware := func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Simulate auth header parsing key := r.Header.Get(HeaderAPIKey) if key == "" { auth := r.Header.Get("Authorization") if len(auth) > 7 && auth[:7] == "Bearer " { key = auth[7:] } } if key == "" { w.WriteHeader(http.StatusUnauthorized) return } // Simulate key validation (without DB) if key != "valid-key" { w.WriteHeader(http.StatusUnauthorized) return } // Add key to context ctx := context.WithValue(r.Context(), contextKeyAPIKey, apiKey) next.ServeHTTP(w, r.WithContext(ctx)) }) } wrappedHandler := middleware(handler) b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { req := httptest.NewRequest("GET", "/projects", nil) req.Header.Set(HeaderAPIKey, "valid-key") rec := httptest.NewRecorder() wrappedHandler.ServeHTTP(rec, req) } } // BenchmarkAuthMiddleware_Bearer benchmarks auth with Bearer token. func BenchmarkAuthMiddleware_Bearer(b *testing.B) { apiKey := &APIKey{ ID: "test-key-id", Name: "benchmark-key", KeyPrefix: "rdev", Scopes: []Scope{ScopeProjectsExecute, ScopeProjectsRead}, CreatedAt: time.Now(), } handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) middleware := func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { key := r.Header.Get(HeaderAPIKey) if key == "" { auth := r.Header.Get("Authorization") if len(auth) > 7 && auth[:7] == "Bearer " { key = auth[7:] } } if key == "" || key != "valid-key" { w.WriteHeader(http.StatusUnauthorized) return } ctx := context.WithValue(r.Context(), contextKeyAPIKey, apiKey) next.ServeHTTP(w, r.WithContext(ctx)) }) } wrappedHandler := middleware(handler) b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { req := httptest.NewRequest("GET", "/projects", nil) req.Header.Set("Authorization", "Bearer valid-key") rec := httptest.NewRecorder() wrappedHandler.ServeHTTP(rec, req) } } // BenchmarkRequireScope benchmarks the scope checking middleware. func BenchmarkRequireScope(b *testing.B) { apiKey := &APIKey{ ID: "test-key-id", Name: "benchmark-key", KeyPrefix: "rdev", Scopes: []Scope{ScopeProjectsExecute, ScopeProjectsRead}, CreatedAt: time.Now(), } handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) scopeMiddleware := RequireScope(ScopeProjectsExecute) wrappedHandler := scopeMiddleware(handler) b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { req := httptest.NewRequest("POST", "/projects/test/claude", nil) // Pre-set the API key in context ctx := context.WithValue(req.Context(), contextKeyAPIKey, apiKey) req = req.WithContext(ctx) rec := httptest.NewRecorder() wrappedHandler.ServeHTTP(rec, req) } } // BenchmarkGetClientIP benchmarks IP extraction from requests. func BenchmarkGetClientIP(b *testing.B) { req := httptest.NewRequest("GET", "/", nil) req.RemoteAddr = "192.168.1.100:12345" b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { _ = getClientIP(req) } } // BenchmarkGetClientIP_XForwardedFor benchmarks IP extraction with X-Forwarded-For. func BenchmarkGetClientIP_XForwardedFor(b *testing.B) { req := httptest.NewRequest("GET", "/", nil) req.Header.Set("X-Forwarded-For", "10.0.0.1, 192.168.1.1, 172.16.0.1") req.RemoteAddr = "127.0.0.1:12345" b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { _ = getClientIP(req) } } // BenchmarkGetClientIP_IPv6 benchmarks IP extraction for IPv6. func BenchmarkGetClientIP_IPv6(b *testing.B) { req := httptest.NewRequest("GET", "/", nil) req.RemoteAddr = "[2001:db8::1]:12345" b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { _ = getClientIP(req) } } // BenchmarkIPAllowlistCheck benchmarks the IP allowlist checking. func BenchmarkIPAllowlistCheck(b *testing.B) { apiKey := &APIKey{ ID: "test-key-id", Name: "benchmark-key", KeyPrefix: "rdev", Scopes: []Scope{ScopeProjectsExecute}, AllowedIPs: []string{"192.168.1.0/24", "10.0.0.0/8", "172.16.0.0/12"}, CreatedAt: time.Now(), } b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { _ = apiKey.IsIPAllowed("192.168.1.100") } } // BenchmarkIPAllowlistCheck_NoAllowlist benchmarks IP check when no allowlist configured. func BenchmarkIPAllowlistCheck_NoAllowlist(b *testing.B) { apiKey := &APIKey{ ID: "test-key-id", Name: "benchmark-key", KeyPrefix: "rdev", Scopes: []Scope{ScopeProjectsExecute}, CreatedAt: time.Now(), } b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { _ = apiKey.IsIPAllowed("192.168.1.100") } } // BenchmarkHealthEndpointSkip benchmarks the path-skip logic for health endpoints. func BenchmarkHealthEndpointSkip(b *testing.B) { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) // Simulate the skip check in middleware middleware := func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { path := r.URL.Path if path == "/health" || path == "/ready" || path == "/metrics" { next.ServeHTTP(w, r) return } // Would do auth here next.ServeHTTP(w, r) }) } wrappedHandler := middleware(handler) b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { req := httptest.NewRequest("GET", "/health", nil) rec := httptest.NewRecorder() wrappedHandler.ServeHTTP(rec, req) } } // BenchmarkConcurrentAuth benchmarks concurrent auth middleware calls. func BenchmarkConcurrentAuth(b *testing.B) { apiKey := &APIKey{ ID: "test-key-id", Name: "benchmark-key", KeyPrefix: "rdev", Scopes: []Scope{ScopeProjectsExecute, ScopeProjectsRead}, CreatedAt: time.Now(), } handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) middleware := func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { key := r.Header.Get(HeaderAPIKey) if key == "" || key != "valid-key" { w.WriteHeader(http.StatusUnauthorized) return } ctx := context.WithValue(r.Context(), contextKeyAPIKey, apiKey) next.ServeHTTP(w, r.WithContext(ctx)) }) } wrappedHandler := middleware(handler) b.ResetTimer() b.ReportAllocs() b.RunParallel(func(pb *testing.PB) { for pb.Next() { req := httptest.NewRequest("GET", "/projects", nil) req.Header.Set(HeaderAPIKey, "valid-key") rec := httptest.NewRecorder() wrappedHandler.ServeHTTP(rec, req) } }) }