From 6c70ddce17e2c3cf4c0ba03719230e125c7b8f9f Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Fri, 28 Aug 2026 10:25:59 +0100 Subject: [PATCH] Handler: add SetCacheControl This interface allows for returning a Cache-Control header that can vary depending on HTTP 404 vs. HTTP 200. The interface could be expanded in future. --- handler.go | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/handler.go b/handler.go index 5edffef..9f13f42 100644 --- a/handler.go +++ b/handler.go @@ -25,10 +25,12 @@ func New(packfile string) (*Handler, error) { } h := &Handler{ - mapped: mapped.Data, - dir: mapped.Directory.Files, - headers: make(map[string]string), - startTime: time.Now(), + mapped: mapped.Data, + dir: mapped.Directory.Files, + headers: make(map[string]string), + cacheControl200: "no-cache", + cacheControl404: "no-cache", + startTime: time.Now(), } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options @@ -42,11 +44,13 @@ func New(packfile string) (*Handler, error) { // Handler implements http.Handler and allows options to be set. type Handler struct { - mapped []byte - dir map[string]*packed.File - headers map[string]string - startTime time.Time - notFound *packed.File + mapped []byte + dir map[string]*packed.File + headers map[string]string + cacheControl200 string + cacheControl404 string + startTime time.Time + notFound *packed.File } // SetHeader allows a custom header to be set on HTTP responses. These are @@ -107,6 +111,19 @@ func (h *Handler) SetNotFound(notFound string) error { return nil } +// SetCacheControl allows control over the cache-control header. If not called, +// "Cache-Control: no-cache" is the default. +// +// The first and second arguments are required, and specify the header to use +// for 200 responses and 404 responses respectively. +// +// TODO: could be expanded to take extra varargs for more specific control over +// particular assets, like different expiry per content-type. +func (h *Handler) SetCacheControl(hdr200, hdr404 string) { + h.cacheControl200 = hdr200 + h.cacheControl404 = hdr404 +} + // ServeHTTP handles requests for files. It supports GET and HEAD methods, with // anything else returning a 405. Exact path matches are required, else a 404 is // returned. @@ -127,6 +144,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { info := h.dir[path.Clean(req.URL.Path)] if info == nil { + w.Header().Set("Cache-Control", h.cacheControl404) if h.notFound == nil { http.NotFound(w, req) return @@ -135,6 +153,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { } // set standard headers + w.Header().Set("Cache-Control", h.cacheControl200) w.Header().Set("Vary", "Accept-Encoding") w.Header().Set("Etag", info.Etag) w.Header().Set("Content-Type", info.ContentType)