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.
This commit is contained in:
Laurence Withers 2026-08-28 10:25:59 +01:00
commit 6c70ddce17

View file

@ -28,6 +28,8 @@ func New(packfile string) (*Handler, error) {
mapped: mapped.Data, mapped: mapped.Data,
dir: mapped.Directory.Files, dir: mapped.Directory.Files,
headers: make(map[string]string), headers: make(map[string]string),
cacheControl200: "no-cache",
cacheControl404: "no-cache",
startTime: time.Now(), startTime: time.Now(),
} }
@ -45,6 +47,8 @@ type Handler struct {
mapped []byte mapped []byte
dir map[string]*packed.File dir map[string]*packed.File
headers map[string]string headers map[string]string
cacheControl200 string
cacheControl404 string
startTime time.Time startTime time.Time
notFound *packed.File notFound *packed.File
} }
@ -107,6 +111,19 @@ func (h *Handler) SetNotFound(notFound string) error {
return nil 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 // 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 // anything else returning a 405. Exact path matches are required, else a 404 is
// returned. // returned.
@ -127,6 +144,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
info := h.dir[path.Clean(req.URL.Path)] info := h.dir[path.Clean(req.URL.Path)]
if info == nil { if info == nil {
w.Header().Set("Cache-Control", h.cacheControl404)
if h.notFound == nil { if h.notFound == nil {
http.NotFound(w, req) http.NotFound(w, req)
return return
@ -135,6 +153,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
} }
// set standard headers // set standard headers
w.Header().Set("Cache-Control", h.cacheControl200)
w.Header().Set("Vary", "Accept-Encoding") w.Header().Set("Vary", "Accept-Encoding")
w.Header().Set("Etag", info.Etag) w.Header().Set("Etag", info.Etag)
w.Header().Set("Content-Type", info.ContentType) w.Header().Set("Content-Type", info.ContentType)