Reorganized internal/api/ package to follow single-concern principle: - api/factory.go (new file, 257 lines) - Extracted component initialization from server.go - initializeComponents(), setupLogger(), initExperimentManager() - initTaskQueue(), initDatabase(), initDatabaseSchema() - initSecurity(), initJupyterServiceManager(), initAuditLogger() - api/middleware.go (new file, 31 lines) - Extracted wrapWithMiddleware() - security middleware chain - Centralized auth, rate limiting, CORS, security headers - api/server.go (reduced from 446 to 212 lines) - Now focused on Server lifecycle: NewServer, Start, WaitForShutdown, Close - Removed initialization logic (moved to factory.go) - Removed middleware wrapper (moved to middleware.go) - api/metrics_middleware.go (existing, 64 lines) - Already had wrapWithMetrics(), left in place Lines redistributed: ~180 lines from monolithic server.go Build status: Compiles successfully
31 lines
928 B
Go
31 lines
928 B
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/jfraeys/fetch_ml/internal/middleware"
|
|
)
|
|
|
|
// wrapWithMiddleware wraps the handler with security middleware
|
|
func (s *Server) wrapWithMiddleware(mux *http.ServeMux) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// Skip auth for WebSocket and health endpoints
|
|
if r.URL.Path == "/ws" || strings.HasPrefix(r.URL.Path, "/health") {
|
|
mux.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
|
|
handler := s.sec.APIKeyAuth(mux)
|
|
handler = s.sec.RateLimit(handler)
|
|
handler = middleware.SecurityHeaders(handler)
|
|
handler = middleware.CORS(s.config.Security.AllowedOrigins)(handler)
|
|
handler = middleware.RequestTimeout(30 * time.Second)(handler)
|
|
handler = middleware.AuditLogger(handler)
|
|
if len(s.config.Security.IPWhitelist) > 0 {
|
|
handler = s.sec.IPWhitelist(s.config.Security.IPWhitelist)(handler)
|
|
}
|
|
handler.ServeHTTP(w, r)
|
|
})
|
|
}
|