Compress more http content-types.

Also, some minor refactoring
This commit is contained in:
Deluan 2022-11-26 13:13:05 -05:00
parent 472f99b2b5
commit 1b5f855bff
5 changed files with 38 additions and 26 deletions

View File

@ -62,7 +62,7 @@ func runNavidrome() {
if err := db.Close(); err != nil {
log.Error("Error closing DB", err)
}
log.Info("Navidrome stopped gracefully. Bye.")
log.Info("Navidrome stopped, bye.")
}()
g, ctx := errgroup.WithContext(context.Background())

View File

@ -61,7 +61,7 @@ func loggerInjector(next http.Handler) http.Handler {
})
}
func robotsTXT(fs fs.FS) func(next http.Handler) http.Handler {
func robotsTXT(fs fs.FS) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasSuffix(r.URL.Path, "/robots.txt") {
@ -74,7 +74,7 @@ func robotsTXT(fs fs.FS) func(next http.Handler) http.Handler {
}
}
func corsHandler() func(h http.Handler) http.Handler {
func corsHandler() func(http.Handler) http.Handler {
return cors.Handler(cors.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{
@ -91,7 +91,7 @@ func corsHandler() func(h http.Handler) http.Handler {
})
}
func secureMiddleware() func(h http.Handler) http.Handler {
func secureMiddleware() func(http.Handler) http.Handler {
sec := secure.New(secure.Options{
ContentTypeNosniff: true,
FrameDeny: true,
@ -102,6 +102,19 @@ func secureMiddleware() func(h http.Handler) http.Handler {
return sec.Handler
}
func compressMiddleware() func(http.Handler) http.Handler {
return middleware.Compress(
5,
"application/xml",
"application/json",
"application/javascript",
"text/html",
"text/plain",
"text/css",
"text/javascript",
)
}
func clientUniqueIdAdder(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

View File

@ -73,6 +73,7 @@ func serveIndex(ds model.DataStore, fs fs.FS) http.HandlerFunc {
"AppConfig": string(j),
"Version": version,
}
w.Header().Set("Content-Type", "text/html")
err = t.Execute(w, data)
if err != nil {
log.Error(r, "Could not execute `index.html` template", err)

View File

@ -42,8 +42,6 @@ func (s *Server) MountRouter(description, urlPath string, subRouter http.Handler
})
}
var startTime = time.Now()
func (s *Server) Run(ctx context.Context, addr string) error {
s.MountRouter("WebUI", consts.URLPathUI, s.frontendAssetsHandler())
server := &http.Server{
@ -55,13 +53,13 @@ func (s *Server) Run(ctx context.Context, addr string) error {
// Start HTTP server in its own goroutine, send a signal (errC) if failed to start
errC := make(chan error)
go func() {
if err := server.ListenAndServe(); err != http.ErrServerClosed {
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
log.Error(ctx, "Could not start server. Aborting", err)
errC <- err
}
}()
log.Info(ctx, "Navidrome server is ready!", "address", addr, "startupTime", time.Since(startTime))
log.Info(ctx, "Navidrome server is ready!", "address", addr, "startupTime", time.Since(consts.ServerStart))
// Wait for a signal to terminate (or an error during startup)
select {
@ -94,7 +92,7 @@ func (s *Server) initRoutes() {
r.Use(middleware.RealIP)
}
r.Use(middleware.Recoverer)
r.Use(middleware.Compress(5, "application/xml", "application/json", "application/javascript"))
r.Use(compressMiddleware())
r.Use(middleware.Heartbeat("/ping"))
r.Use(clientUniqueIdAdder)
r.Use(loggerInjector)

View File

@ -166,8 +166,14 @@ func (api *Router) routes() http.Handler {
return r
}
// Add the Subsonic handler that requires a http.ResponseWriter, with and without `.view` extension.
// Ex: if path = `stream` it will create the routes `/stream` and `/stream.view`
// Add a Subsonic handler
func h(r chi.Router, path string, f handler) {
hr(r, path, func(_ http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
return f(r)
})
}
// Add a Subsonic handler that requires a http.ResponseWriter (ex: stream, getCoverArt...)
func hr(r chi.Router, path string, f handlerRaw) {
handle := func(w http.ResponseWriter, r *http.Request) {
res, err := f(w, r)
@ -194,28 +200,18 @@ func hr(r chi.Router, path string, f handlerRaw) {
sendResponse(w, r, res)
}
}
r.HandleFunc("/"+path, handle)
r.HandleFunc("/"+path+".view", handle)
}
// Add the Subsonic handler, with and without `.view` extension
// Ex: if path = `ping` it will create the routes `/ping` and `/ping.view`
func h(r chi.Router, path string, f handler) {
hr(r, path, func(_ http.ResponseWriter, r *http.Request) (*responses.Subsonic, error) {
return f(r)
})
addHandler(r, path, handle)
}
// Add a handler that returns 501 - Not implemented. Used to signal that an endpoint is not implemented yet
func h501(r *chi.Mux, paths ...string) {
func h501(r chi.Router, paths ...string) {
for _, path := range paths {
handle := func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Cache-Control", "no-cache")
w.WriteHeader(501)
_, _ = w.Write([]byte("This endpoint is not implemented, but may be in future releases"))
}
r.HandleFunc("/"+path, handle)
r.HandleFunc("/"+path+".view", handle)
addHandler(r, path, handle)
}
}
@ -226,11 +222,15 @@ func h410(r chi.Router, paths ...string) {
w.WriteHeader(410)
_, _ = w.Write([]byte("This endpoint will not be implemented"))
}
r.HandleFunc("/"+path, handle)
r.HandleFunc("/"+path+".view", handle)
addHandler(r, path, handle)
}
}
func addHandler(r chi.Router, path string, handle func(w http.ResponseWriter, r *http.Request)) {
r.HandleFunc("/"+path, handle)
r.HandleFunc("/"+path+".view", handle)
}
func sendError(w http.ResponseWriter, r *http.Request, err error) {
response := newResponse()
code := responses.ErrorGeneric