Files
navidrome/server/nativeapi/native_api.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

137 lines
3.6 KiB
Go
Raw Normal View History

2021-06-13 19:15:41 -04:00
package nativeapi
2020-01-19 19:34:54 -05:00
import (
2020-01-19 20:40:18 -05:00
"context"
2020-01-19 19:34:54 -05:00
"net/http"
2020-01-19 20:40:18 -05:00
"net/url"
"strings"
2020-01-19 19:34:54 -05:00
2020-01-19 20:40:18 -05:00
"github.com/deluan/rest"
2021-05-11 17:21:18 -04:00
"github.com/go-chi/chi/v5"
"github.com/navidrome/navidrome/conf"
"github.com/navidrome/navidrome/core"
2020-01-23 19:44:08 -05:00
"github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/server"
"github.com/navidrome/navidrome/server/events"
2020-01-19 19:34:54 -05:00
)
type Router struct {
http.Handler
ds model.DataStore
broker events.Broker
share core.Share
2020-01-19 19:34:54 -05:00
}
func New(ds model.DataStore, broker events.Broker, share core.Share) *Router {
r := &Router{ds: ds, broker: broker, share: share}
r.Handler = r.routes()
return r
2020-01-19 19:34:54 -05:00
}
2021-06-13 19:15:41 -04:00
func (n *Router) routes() http.Handler {
2020-01-19 19:34:54 -05:00
r := chi.NewRouter()
2020-01-19 20:40:18 -05:00
// Public
2021-06-13 19:15:41 -04:00
n.RX(r, "/translation", newTranslationRepository, false)
// Protected
r.Group(func(r chi.Router) {
r.Use(server.Authenticator(n.ds))
r.Use(server.JWTRefresher)
n.R(r, "/user", model.User{}, true)
n.R(r, "/song", model.MediaFile{}, false)
n.R(r, "/album", model.Album{}, false)
n.R(r, "/artist", model.Artist{}, false)
n.R(r, "/genre", model.Genre{}, false)
n.R(r, "/player", model.Player{}, true)
n.R(r, "/playlist", model.Playlist{}, true)
n.R(r, "/transcoding", model.Transcoding{}, conf.Server.EnableTranscodingConfig)
n.RX(r, "/share", n.share.NewRepository, true)
n.addPlaylistTrackRoute(r)
// Keepalive endpoint to be used to keep the session valid (ex: while playing songs)
r.Get("/keepalive/*", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"response":"ok", "id":"keepalive"}`))
})
2020-01-22 18:35:44 -05:00
if conf.Server.DevActivityPanel {
r.Handle("/events", n.broker)
}
})
2020-01-22 18:35:44 -05:00
2020-01-19 19:34:54 -05:00
return r
}
2020-01-19 20:40:18 -05:00
2021-06-13 19:15:41 -04:00
func (n *Router) R(r chi.Router, pathPrefix string, model interface{}, persistable bool) {
constructor := func(ctx context.Context) rest.Repository {
2021-06-13 19:15:41 -04:00
return n.ds.Resource(ctx, model)
}
2021-06-13 19:15:41 -04:00
n.RX(r, pathPrefix, constructor, persistable)
2020-05-01 18:29:50 -04:00
}
2021-06-13 19:15:41 -04:00
func (n *Router) RX(r chi.Router, pathPrefix string, constructor rest.RepositoryConstructor, persistable bool) {
2020-01-19 20:40:18 -05:00
r.Route(pathPrefix, func(r chi.Router) {
r.Get("/", rest.GetAll(constructor))
if persistable {
r.Post("/", rest.Post(constructor))
}
2020-05-01 18:29:50 -04:00
r.Route("/{id}", func(r chi.Router) {
2021-05-02 15:23:51 -04:00
r.Use(urlParams)
r.Get("/", rest.Get(constructor))
if persistable {
r.Put("/", rest.Put(constructor))
r.Delete("/", rest.Delete(constructor))
}
2020-01-19 20:40:18 -05:00
})
})
}
2021-06-13 19:15:41 -04:00
func (n *Router) addPlaylistTrackRoute(r chi.Router) {
r.Route("/playlist/{playlistId}/tracks", func(r chi.Router) {
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
2021-06-13 19:15:41 -04:00
getPlaylist(n.ds)(w, r)
})
2021-10-26 14:05:28 -04:00
r.With(urlParams).Route("/", func(r chi.Router) {
r.Delete("/", func(w http.ResponseWriter, r *http.Request) {
deleteFromPlaylist(n.ds)(w, r)
})
r.Post("/", func(w http.ResponseWriter, r *http.Request) {
addToPlaylist(n.ds)(w, r)
})
})
r.Route("/{id}", func(r chi.Router) {
2021-05-02 15:23:51 -04:00
r.Use(urlParams)
2020-06-04 19:05:41 -04:00
r.Put("/", func(w http.ResponseWriter, r *http.Request) {
2021-06-13 19:15:41 -04:00
reorderItem(n.ds)(w, r)
2020-06-04 19:05:41 -04:00
})
2020-05-16 18:10:08 -04:00
r.Delete("/", func(w http.ResponseWriter, r *http.Request) {
2021-06-13 19:15:41 -04:00
deleteFromPlaylist(n.ds)(w, r)
2020-05-16 18:10:08 -04:00
})
})
})
}
2020-01-19 20:40:18 -05:00
// Middleware to convert Chi URL params (from Context) to query params, as expected by our REST package
2021-05-02 15:23:51 -04:00
func urlParams(next http.Handler) http.Handler {
2020-01-19 20:40:18 -05:00
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := chi.RouteContext(r.Context())
parts := make([]string, 0)
for i, key := range ctx.URLParams.Keys {
value := ctx.URLParams.Values[i]
if key == "*" {
continue
}
parts = append(parts, url.QueryEscape(":"+key)+"="+url.QueryEscape(value))
}
q := strings.Join(parts, "&")
if r.URL.RawQuery == "" {
r.URL.RawQuery = q
} else {
r.URL.RawQuery += "&" + q
}
next.ServeHTTP(w, r)
})
}