package api import ( "net/http" "os" "path/filepath" "strings" "time" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/cors" ) func NewRouter() http.Handler { r := chi.NewRouter() // Middleware r.Use(middleware.Logger) r.Use(middleware.Recoverer) r.Use(middleware.Timeout(60 * time.Second)) // CORS r.Use(cors.Handler(cors.Options{ AllowedOrigins: []string{"http://localhost:3000", "http://127.0.0.1:3000", "http://localhost:5173"}, // Added Vite default port AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, ExposedHeaders: []string{"Link"}, AllowCredentials: true, MaxAge: 300, })) r.Route("/api", func(r chi.Router) { r.Get("/health", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok")) }) r.Get("/search", SearchTracks) r.Get("/stream/{id}", StreamAudio) r.Get("/lyrics", GetLyrics) r.Get("/artist-image", GetArtistImage) r.Post("/download", DownloadTrack) r.Post("/settings/update-ytdlp", UpdateSimBinary) }) // Serve Static Files (SPA) workDir, _ := os.Getwd() filesDir := http.Dir(filepath.Join(workDir, "static")) FileServer(r, "/", filesDir) return r } // FileServer conveniently sets up a http.FileServer handler to serve // static files from a http.FileSystem. func FileServer(r chi.Router, path string, root http.FileSystem) { if strings.ContainsAny(path, "{}*") { panic("FileServer does not permit any URL parameters.") } if path != "/" && path[len(path)-1] != '/' { r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP) path += "/" } path += "*" r.Get(path, func(w http.ResponseWriter, r *http.Request) { rctx := chi.RouteContext(r.Context()) pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*") fs := http.StripPrefix(pathPrefix, http.FileServer(root)) // Check if file exists, otherwise serve index.html (SPA) f, err := root.Open(r.URL.Path) if err != nil && os.IsNotExist(err) { http.ServeFile(w, r, filepath.Join("static", "index.html")) return } if f != nil { f.Close() } fs.ServeHTTP(w, r) }) }