diff --git a/pkg/api/ui_handler.go b/pkg/api/ui_handler.go index c88f5d1caf7..d743a772822 100644 --- a/pkg/api/ui_handler.go +++ b/pkg/api/ui_handler.go @@ -6,6 +6,7 @@ import ( "os" "path" "strings" + "time" "github.com/rakyll/statik/fs" "github.com/treeverse/lakefs/pkg/auth" @@ -15,13 +16,51 @@ import ( "github.com/treeverse/lakefs/pkg/webui" ) +// Taken from https://github.com/mytrile/nocache +var noCacheHeaders = map[string]string{ + "Expires": time.Unix(0, 0).Format(time.RFC1123), + "Cache-Control": "no-cache, private, max-age=0", + "Pragma": "no-cache", + "X-Accel-Expires": "0", +} + +var etagHeaders = []string{ + "ETag", + "If-Modified-Since", + "If-Match", + "If-None-Match", + "If-Range", + "If-Unmodified-Since", +} + func NewUIHandler(authService auth.Service, gatewayDomains []string) http.Handler { mux := http.NewServeMux() staticFiles, _ := fs.NewWithNamespace(webui.Webui) - mux.Handle("/", NewHandlerWithDefault(staticFiles, http.FileServer(staticFiles), "/", gatewayDomains)) + fileServer := http.FileServer(staticFiles) + noCacheFileServer := NoCacheHandler(fileServer) + mux.Handle("/", NewHandlerWithDefault(staticFiles, noCacheFileServer, "/", gatewayDomains)) return mux } +// NoCacheHandler based on github.com/zenazn/goji's NoCache +func NoCacheHandler(handler http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Delete any ETag headers that may have been set + for _, v := range etagHeaders { + if r.Header.Get(v) != "" { + r.Header.Del(v) + } + } + + // Set our NoCache headers + for k, v := range noCacheHeaders { + w.Header().Set(k, v) + } + + handler.ServeHTTP(w, r) + }) +} + func NewHandlerWithDefault(root http.FileSystem, handler http.Handler, defaultPath string, gatewayDomains []string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if isGatewayRequest(r) {