From 7f6074b3008cc1237b7f4b81313e5e4645fe5aee Mon Sep 17 00:00:00 2001 From: Doug Clark Date: Wed, 8 Jan 2020 14:43:59 -0600 Subject: [PATCH] GH-13570 Allow /static/plugins/* endpoint responses to be cached (except for 404s) (#13592) * Reinstate caching on /static/plugins/* endpoint except for 404s * fix struct name and change default behavior for staticFilesHandler --- web/static.go | 25 +++++++++++++------------ web/web_test.go | 6 +++--- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/web/static.go b/web/static.go index bf44044825..3c6970689e 100644 --- a/web/static.go +++ b/web/static.go @@ -34,7 +34,7 @@ func (w *Web) InitStatic() { mime.AddExtensionType(".wasm", "application/wasm") staticHandler := staticFilesHandler(http.StripPrefix(path.Join(subpath, "static"), http.FileServer(http.Dir(staticDir)))) - pluginHandler := staticFilesWithValidationHandler(http.StripPrefix(path.Join(subpath, "static", "plugins"), http.FileServer(http.Dir(*w.ConfigService.Config().PluginSettings.ClientDirectory)))) + pluginHandler := staticFilesHandler(http.StripPrefix(path.Join(subpath, "static", "plugins"), http.FileServer(http.Dir(*w.ConfigService.Config().PluginSettings.ClientDirectory)))) if *w.ConfigService.Config().ServiceSettings.WebserverMode == "gzip" { staticHandler = gziphandler.GzipHandler(staticHandler) @@ -77,6 +77,9 @@ func root(c *Context, w http.ResponseWriter, r *http.Request) { func staticFilesHandler(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + //wrap our ResponseWriter with our no-cache 404-handler + w = ¬FoundNoCacheResponseWriter{ResponseWriter: w} + w.Header().Set("Cache-Control", "max-age=31556926, public") if strings.HasSuffix(r.URL.Path, "/") { @@ -87,18 +90,16 @@ func staticFilesHandler(handler http.Handler) http.Handler { }) } -func staticFilesWithValidationHandler(handler http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Require validation from any cache, achieved via Last-Modified and the - // http.FileServer. - w.Header().Set("Cache-Control", "no-cache, public") +type notFoundNoCacheResponseWriter struct { + http.ResponseWriter +} - if strings.HasSuffix(r.URL.Path, "/") { - http.NotFound(w, r) - return - } - handler.ServeHTTP(w, r) - }) +func (w *notFoundNoCacheResponseWriter) WriteHeader(statusCode int) { + if statusCode == http.StatusNotFound { + // we have a 404, update our cache header first then fall through + w.Header().Set("Cache-Control", "no-cache, public") + } + w.ResponseWriter.WriteHeader(statusCode) } func robotsHandler(w http.ResponseWriter, r *http.Request) { diff --git a/web/web_test.go b/web/web_test.go index 7d7dc71031..b8833248b2 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -184,7 +184,7 @@ func TestStaticFilesRequest(t *testing.T) { th.Web.MainRouter.ServeHTTP(res, req) assert.Equal(t, http.StatusOK, res.Code) assert.Equal(t, mainJS, res.Body.String()) - assert.Equal(t, []string{"no-cache, public"}, res.Result().Header[http.CanonicalHeaderKey("Cache-Control")]) + assert.Equal(t, []string{"max-age=31556926, public"}, res.Result().Header[http.CanonicalHeaderKey("Cache-Control")]) // Verify cached access to the bundle with an If-Modified-Since timestamp in the future future := time.Now().Add(24 * time.Hour) @@ -194,7 +194,7 @@ func TestStaticFilesRequest(t *testing.T) { th.Web.MainRouter.ServeHTTP(res, req) assert.Equal(t, http.StatusNotModified, res.Code) assert.Empty(t, res.Body.String()) - assert.Equal(t, []string{"no-cache, public"}, res.Result().Header[http.CanonicalHeaderKey("Cache-Control")]) + assert.Equal(t, []string{"max-age=31556926, public"}, res.Result().Header[http.CanonicalHeaderKey("Cache-Control")]) // Verify access to the bundle with an If-Modified-Since timestamp in the past past := time.Now().Add(-24 * time.Hour) @@ -204,7 +204,7 @@ func TestStaticFilesRequest(t *testing.T) { th.Web.MainRouter.ServeHTTP(res, req) assert.Equal(t, http.StatusOK, res.Code) assert.Equal(t, mainJS, res.Body.String()) - assert.Equal(t, []string{"no-cache, public"}, res.Result().Header[http.CanonicalHeaderKey("Cache-Control")]) + assert.Equal(t, []string{"max-age=31556926, public"}, res.Result().Header[http.CanonicalHeaderKey("Cache-Control")]) // Verify handling of 404. req, _ = http.NewRequest("GET", "/static/plugins/com.mattermost.sample/404.js", nil)