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

@ -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)