package main import ( "io/fs" "net/http" ) // RegisterAPI sets up all HTTP routes on the given mux. func RegisterAPI(mux *http.ServeMux, executor *Executor, scheduler *Scheduler, frontendFS fs.FS) { // API routes. mux.HandleFunc("GET /api/dags", handleListDags(executor)) mux.HandleFunc("GET /api/dags/{name}", handleGetDag(executor)) mux.HandleFunc("POST /api/dags/{name}/run", handleRunDag(executor)) mux.HandleFunc("GET /api/runs", handleListRuns(executor)) mux.HandleFunc("GET /api/runs/{id}", handleGetRun(executor)) mux.HandleFunc("POST /api/scheduler/start", handleSchedulerStart(scheduler)) mux.HandleFunc("POST /api/scheduler/stop", handleSchedulerStop(scheduler)) mux.HandleFunc("GET /api/scheduler/status", handleSchedulerStatus(scheduler)) // Frontend SPA fallback. if frontendFS != nil { mux.Handle("/", spaHandler(frontendFS)) } } // spaHandler serves static files from the embedded FS, falling back to index.html // for unknown paths (SPA client-side routing). func spaHandler(fsys fs.FS) http.Handler { fileServer := http.FileServer(http.FS(fsys)) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Try to serve the file directly. path := r.URL.Path if path == "/" { path = "index.html" } else { path = path[1:] // strip leading / } if _, err := fs.Stat(fsys, path); err != nil { // File not found — serve index.html for SPA routing. r.URL.Path = "/" } fileServer.ServeHTTP(w, r) }) }