diff --git a/server/ctrladmin/ctrl.go b/server/ctrladmin/ctrl.go index a4b4b94..a8626ad 100644 --- a/server/ctrladmin/ctrl.go +++ b/server/ctrladmin/ctrl.go @@ -177,6 +177,9 @@ func (c *Controller) H(h adminHandler) http.Handler { return } w.Header().Set("Content-Type", "text/html; charset=utf-8") + if resp.code != 0 { + w.WriteHeader(resp.code) + } if _, err := buff.WriteTo(w); err != nil { log.Printf("error writing to response buffer: %v\n", err) } diff --git a/server/ctrladmin/handlers.go b/server/ctrladmin/handlers.go index 73dd5e5..6eeac56 100644 --- a/server/ctrladmin/handlers.go +++ b/server/ctrladmin/handlers.go @@ -13,7 +13,7 @@ import ( ) func (c *Controller) ServeNotFound(r *http.Request) *Response { - return &Response{template: "not_found.tmpl"} + return &Response{template: "not_found.tmpl", code: 404} } func (c *Controller) ServeLogin(r *http.Request) *Response { diff --git a/server/ctrlsubsonic/middleware.go b/server/ctrlsubsonic/middleware.go index b9f68a3..cfdb9fa 100644 --- a/server/ctrlsubsonic/middleware.go +++ b/server/ctrlsubsonic/middleware.go @@ -34,7 +34,7 @@ func (c *Controller) WithParams(next http.Handler) http.Handler { }) } -func (c *Controller) WithUser(next http.Handler) http.Handler { +func (c *Controller) WithRequiredParams(next http.Handler) http.Handler { requiredParameters := []string{ "u", "v", "c", } @@ -45,10 +45,17 @@ func (c *Controller) WithUser(next http.Handler) http.Handler { if param != "" { continue } - writeResp(w, r, spec.NewError(10, "please provide a `%s` parameter", req)) + _ = writeResp(w, r, spec.NewError(10, + "please provide a `%s` parameter", req)) return } - // + next.ServeHTTP(w, r) + }) +} + +func (c *Controller) WithUser(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + params := r.Context().Value(CtxParams).(params.Params) username := params.Get("u") password := params.Get("p") token := params.Get("t") @@ -57,12 +64,14 @@ func (c *Controller) WithUser(next http.Handler) http.Handler { passwordAuth := token == "" && salt == "" tokenAuth := password == "" if tokenAuth == passwordAuth { - writeResp(w, r, spec.NewError(10, "please provide `t` and `s`, or just `p`")) + _ = writeResp(w, r, spec.NewError(10, + "please provide `t` and `s`, or just `p`")) return } user := c.DB.GetUserFromName(username) if user == nil { - writeResp(w, r, spec.NewError(40, "invalid username `%s`", username)) + _ = writeResp(w, r, spec.NewError(40, + "invalid username `%s`", username)) return } var credsOk bool @@ -72,7 +81,7 @@ func (c *Controller) WithUser(next http.Handler) http.Handler { credsOk = checkCredsBasic(user.Password, password) } if !credsOk { - writeResp(w, r, spec.NewError(40, "invalid password")) + _ = writeResp(w, r, spec.NewError(40, "invalid password")) return } withUser := context.WithValue(r.Context(), CtxUser, user) diff --git a/server/server.go b/server/server.go index 7d9a374..32eabfe 100644 --- a/server/server.go +++ b/server/server.go @@ -76,7 +76,6 @@ func (s *Server) SetupAdmin() error { // begin public routes (creates session) routPublic := s.router.PathPrefix("/admin").Subrouter() routPublic.Use(ctrl.WithSession) - routPublic.NotFoundHandler = ctrl.H(ctrl.ServeNotFound) routPublic.Handle("/login", ctrl.H(ctrl.ServeLogin)) routPublic.HandleFunc("/login_do", ctrl.ServeLoginDo) // "raw" handler, updates session assets.PrefixDo("static", func(path string, asset *assets.EmbeddedAsset) { @@ -111,14 +110,20 @@ func (s *Server) SetupAdmin() error { routAdmin.Handle("/update_lastfm_api_key", ctrl.H(ctrl.ServeUpdateLastFMAPIKey)) routAdmin.Handle("/update_lastfm_api_key_do", ctrl.H(ctrl.ServeUpdateLastFMAPIKeyDo)) routAdmin.Handle("/start_scan_do", ctrl.H(ctrl.ServeStartScanDo)) + // middlewares should be run for not found handler + // https://github.com/gorilla/mux/issues/416 + notFoundHandler := ctrl.H(ctrl.ServeNotFound) + notFoundRoute := routPublic.NewRoute().Handler(notFoundHandler) + routPublic.NotFoundHandler = notFoundRoute.GetHandler() return nil } func (s *Server) SetupSubsonic() error { ctrl := ctrlsubsonic.New(s.ctrlBase) rout := s.router.PathPrefix("/rest").Subrouter() - rout.Use(ctrl.WithValidSubsonicArgs) - rout.NotFoundHandler = ctrl.H(ctrl.ServeNotFound) + rout.Use(ctrl.WithParams) + rout.Use(ctrl.WithRequiredParams) + rout.Use(ctrl.WithUser) // // begin common rout.Handle("/getLicense{_:(?:\\.view)?}", ctrl.H(ctrl.ServeGetLicence)) @@ -151,6 +156,11 @@ func (s *Server) SetupSubsonic() error { rout.Handle("/getMusicDirectory{_:(?:\\.view)?}", ctrl.H(ctrl.ServeGetMusicDirectory)) rout.Handle("/getAlbumList{_:(?:\\.view)?}", ctrl.H(ctrl.ServeGetAlbumList)) rout.Handle("/search2{_:(?:\\.view)?}", ctrl.H(ctrl.ServeSearchTwo)) + // middlewares should be run for not found handler + // https://github.com/gorilla/mux/issues/416 + notFoundHandler := ctrl.H(ctrl.ServeNotFound) + notFoundRoute := rout.NewRoute().Handler(notFoundHandler) + rout.NotFoundHandler = notFoundRoute.GetHandler() return nil }