// Package subsonic implements a Subsonic-compatible REST API surface under // /rest. It exists for third-party Subsonic clients (Symfonium, Substreamer, // DSub, Tempo, play:Sub, …). Minstrel's own clients use the native /api/* // surface, which has modern auth; /rest/* retains Subsonic's legacy auth for // compatibility only. See docs/auth.md for the security posture. package subsonic import ( "log/slog" "net/http" "github.com/go-chi/chi/v5" "github.com/jackc/pgx/v5/pgxpool" ) // Mount attaches Subsonic handlers at /rest on r. Endpoints are exposed at // both /rest/foo and /rest/foo.view because client conventions vary. Both // GET and POST are accepted; Subsonic's auth params live in the query string // either way. func Mount(r chi.Router, pool *pgxpool.Pool, logger *slog.Logger, cfg Config) { b := &browseHandlers{pool: pool} m := newMediaHandlers(pool) r.Route("/rest", func(sub chi.Router) { sub.Use(Middleware(pool, cfg)) register(sub, "/ping", handlePing) register(sub, "/getLicense", handleGetLicense) register(sub, "/getMusicFolders", b.getMusicFolders) register(sub, "/getIndexes", b.getIndexes) register(sub, "/getArtists", b.getArtists) register(sub, "/getArtist", b.getArtist) register(sub, "/getAlbum", b.getAlbum) register(sub, "/getAlbumList2", b.getAlbumList2) register(sub, "/getSong", b.getSong) register(sub, "/search3", b.search3) register(sub, "/stream", m.handleStream) register(sub, "/download", m.handleDownload) register(sub, "/getCoverArt", m.handleGetCoverArt) register(sub, "/scrobble", m.handleScrobble) _ = logger }) } func register(r chi.Router, path string, h func(http.ResponseWriter, *http.Request)) { r.Get(path, h) r.Post(path, h) r.Get(path+".view", h) r.Post(path+".view", h) }