Stop browsers from caching songs
/music/rand and the other song endpoints return a different song from the same URL, but the responses had a Last-Modified header and no Cache-Control, so browsers cached them. The same song played again and the server never picked a new one, so /music/addQue added nothing. Send Cache-Control: no-store again, as the server did before the rewrite. Also allow the Cache-Control request header in CORS, which the frontend sends to bypass responses that browsers have already cached.
This commit is contained in:
1 parent
d31bf3551c
commit
76a1b946eb
3 files changed
+27
-2
No files matched your search
@@ -52,9 +52,21 @@ func streamOpenFile(f *os.File, contentType string, audio bool) (*huma.StreamRes
|
||||
}
|
||||
|
||||
// streamSong streams the song at path, or returns err mapped to an API error.
|
||||
// The same URL returns a different song each time (random songs, next, previous),
|
||||
// so browsers must not cache it. Without this they cache the response because of
|
||||
// its Last-Modified header, and play the same song again.
|
||||
func streamSong(path string, err error) (*huma.StreamResponse, error) {
|
||||
if err != nil {
|
||||
return nil, apiError(err)
|
||||
}
|
||||
return streamFile(path, "audio/mpeg", true)
|
||||
resp, err := streamFile(path, "audio/mpeg", true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body := resp.Body
|
||||
resp.Body = func(ctx huma.Context) {
|
||||
ctx.SetHeader("Cache-Control", "no-store")
|
||||
body(ctx)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -92,6 +92,19 @@ func TestMusicQueueEndsAfterSync(t *testing.T) {
|
||||
assert.JSONEq(t, "[]", rec.Body.String())
|
||||
}
|
||||
|
||||
func TestMusicSongsAreNotCached(t *testing.T) {
|
||||
e := newTestEnv(t)
|
||||
e.addSong("Game A", "Song", "x")
|
||||
e.do(http.MethodGet, "/api/v1/music/rand")
|
||||
e.do(http.MethodGet, "/api/v1/music/addQue")
|
||||
for _, path := range []string{"/api/v1/music/rand", "/api/v1/music/rand/low", "/api/v1/music/rand/classic",
|
||||
"/api/v1/music/next", "/api/v1/music/previous", "/api/v1/music?song=0", "/api/v1/music/soundTest"} {
|
||||
rec := e.do(http.MethodGet, path)
|
||||
require.Equal(t, http.StatusOK, rec.Code, path)
|
||||
assert.Equal(t, "no-store", rec.Header().Get("Cache-Control"), path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMusicRangeRequest(t *testing.T) {
|
||||
e := newTestEnv(t)
|
||||
e.addSong("Game A", "Song", "0123456789")
|
||||
|
||||
@@ -46,7 +46,7 @@ func (s *Server) routes() (*echo.Echo, huma.API) {
|
||||
e.Use(echoMiddleware.CORSWithConfig(echoMiddleware.CORSConfig{
|
||||
AllowOrigins: s.cfg.CORSAllowedOrigins,
|
||||
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"},
|
||||
AllowHeaders: []string{"Accept", "Authorization", "Content-Type", "Range", middleware.QueueHeader},
|
||||
AllowHeaders: []string{"Accept", "Authorization", "Cache-Control", "Content-Type", "Range", middleware.QueueHeader},
|
||||
ExposeHeaders: []string{middleware.QueueHeader, "Content-Range", "Accept-Ranges"},
|
||||
MaxAge: 300,
|
||||
}))
|
||||
|
||||
Reference in new issue
Block a user