package api import ( "net/http" "os" "github.com/jfraeys/fetch_ml/internal/api/datasets" "github.com/jfraeys/fetch_ml/internal/api/jobs" "github.com/jfraeys/fetch_ml/internal/api/jupyter" "github.com/jfraeys/fetch_ml/internal/api/ws" "github.com/jfraeys/fetch_ml/internal/prommetrics" "github.com/labstack/echo/v4" ) // registerRoutes sets up all HTTP routes and handlers func (s *Server) registerRoutes(mux *http.ServeMux) { // Register Prometheus metrics endpoint (if enabled) if s.config.Monitoring.Prometheus.Enabled { s.promMetrics = prommetrics.New() s.logger.Info("prometheus metrics initialized") // Register metrics endpoint metricsPath := s.config.Monitoring.Prometheus.Path if metricsPath == "" { metricsPath = "/metrics" } mux.Handle(metricsPath, s.promMetrics.Handler()) s.logger.Info("metrics endpoint registered", "path", metricsPath) } // Register health check endpoints (if enabled) if s.config.Monitoring.HealthChecks.Enabled { s.registerHealthRoutes(mux) } // Register WebSocket endpoint s.registerWebSocketRoutes(mux) // Register new REST API endpoints for TUI jobsHandler := jobs.NewHandler( s.expManager, s.logger, s.taskQueue, s.db, s.config.BuildAuthConfig(), nil, ) // Experiment history endpoint: GET /api/experiments/:id/history mux.HandleFunc("GET /api/experiments/{id}/history", jobsHandler.GetExperimentHistoryHTTP) // Team jobs endpoint: GET /api/jobs?all_users=true mux.HandleFunc("GET /api/jobs", jobsHandler.ListAllJobsHTTP) // Register OpenAPI-generated routes with Echo router s.registerOpenAPIRoutes(mux, jobsHandler) // Register API documentation endpoint s.registerDocsRoutes(mux) } // registerDocsRoutes sets up API documentation serving func (s *Server) registerDocsRoutes(mux *http.ServeMux) { // Check if docs directory exists if _, err := os.Stat("docs/api"); err == nil { docsFS := http.FileServer(http.Dir("docs/api")) mux.Handle("/docs/", http.StripPrefix("/docs/", docsFS)) s.logger.Info("API documentation endpoint registered", "path", "/docs/") } else { s.logger.Debug("API documentation not available", "path", "docs/api") } } // registerOpenAPIRoutes sets up Echo router with generated OpenAPI handlers func (s *Server) registerOpenAPIRoutes(mux *http.ServeMux, jobsHandler *jobs.Handler) { // Create Echo instance for OpenAPI-generated routes e := echo.New() // Create jupyter handler jupyterHandler := jupyter.NewHandler( s.logger, s.jupyterServiceMgr, s.config.BuildAuthConfig(), ) // Create datasets handler datasetsHandler := datasets.NewHandler( s.logger, s.db, s.config.DataDir, ) // Create adapter implementing ServerInterface handlerAdapter := NewHandlerAdapter( jobsHandler, jupyterHandler, datasetsHandler, ) // Register generated OpenAPI routes RegisterHandlers(e, handlerAdapter) // Wrap Echo router to work with existing middleware chain echoHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { e.ServeHTTP(w, r) }) // Register Echo router at /v1/ prefix // These paths take precedence over legacy routes mux.Handle("/v1/", echoHandler) s.logger.Info("OpenAPI-generated routes registered with Echo router") } // registerHealthRoutes sets up health check endpoints func (s *Server) registerHealthRoutes(mux *http.ServeMux) { healthHandler := NewHealthHandler(s) healthHandler.RegisterRoutes(mux) s.logger.Info("health check endpoints registered") } // registerWebSocketRoutes sets up WebSocket endpoint func (s *Server) registerWebSocketRoutes(mux *http.ServeMux) { // Initialize audit logger for WebSocket connections auditLogger := s.initAuditLogger() // Register WebSocket handler with security config and audit logger securityCfg := getSecurityConfig(s.config) // Create jobs handler jobsHandler := jobs.NewHandler( s.expManager, s.logger, s.taskQueue, s.db, s.config.BuildAuthConfig(), nil, // privacyEnforcer - not enabled for now ) // Create jupyter handler jupyterHandler := jupyter.NewHandler( s.logger, s.jupyterServiceMgr, s.config.BuildAuthConfig(), ) // Create datasets handler datasetsHandler := datasets.NewHandler( s.logger, s.db, s.config.DataDir, ) wsHandler := ws.NewHandler( s.config.BuildAuthConfig(), s.logger, s.expManager, s.config.DataDir, s.taskQueue, s.db, s.jupyterServiceMgr, securityCfg, auditLogger, jobsHandler, jupyterHandler, datasetsHandler, ) mux.Handle("/ws", wsHandler) s.logger.Info("websocket endpoint registered") }