package server import ( "net/http" "music-server/cmd/web" "music-server/internal/logging" "music-server/internal/server/middleware" "github.com/a-h/templ" "github.com/danielgtaylor/huma/v2" "github.com/labstack/echo/v5" echoMiddleware "github.com/labstack/echo/v5/middleware" "go.uber.org/zap" ) func (s *Server) RegisterRoutes() http.Handler { e, _ := s.routes() return e } // OpenAPISpec returns the API description. It needs no database or configuration: // the handlers are registered but never called. func OpenAPISpec() *huma.OpenAPI { _, a := (&Server{}).routes() return a.v1.OpenAPI() } func (s *Server) routes() (*echo.Echo, apis) { e := echo.New() e.HTTPErrorHandler = httpErrorHandler if len(s.cfg.TrustedProxies) > 0 { var trust []echo.TrustOption for _, ipNet := range s.cfg.TrustedProxies { trust = append(trust, echo.TrustIPRange(ipNet)) } e.IPExtractor = echo.ExtractIPFromXFFHeader(trust...) } e.Use(logging.RequestLogger()) e.Use(echoMiddleware.Recover()) e.Use(echoMiddleware.CORSWithConfig(echoMiddleware.CORSConfig{ AllowOrigins: []string{"https://*", "http://*"}, AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"}, AllowHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, AllowCredentials: true, MaxAge: 300, })) // The API: /api/v1 is documented at /docs and /openapi.json; legacy routes are hidden. a := newAPIs(e) a.v1.UseMiddleware(middleware.ClientInfo, middleware.TokenAuth(a.v1, s.q, s.cfg.DisableSessionAuth)) a.legacy.UseMiddleware(middleware.ClientInfo, middleware.Deprecation) s.registerToken(a) s.registerMisc(a) s.registerSync(a) s.registerMusic(a) s.registerLibrary(a) s.registerStatistics(a) // Older links to the spec and docs. e.GET("/openapi", redirect("/openapi.json")) e.GET("/swagger/*", redirect("/docs")) // Search page and frontend. e.GET("/assets/*", echo.WrapHandler(http.FileServer(http.FS(web.Assets)))) e.GET("/search", echo.WrapHandler(templ.Handler(web.SearchForm()))) e.POST("/find", echo.WrapHandler(web.NewSearchHandler(s.search))) e.Static("/", s.cfg.FrontendPath) for _, r := range e.Router().Routes() { logging.GetLogger().Debug("Registered route", zap.String("method", r.Method), zap.String("path", r.Path)) } return e, a } func redirect(to string) echo.HandlerFunc { return func(c *echo.Context) error { return c.Redirect(http.StatusMovedPermanently, to) } }