diff --git a/internal/web/render.go b/internal/web/render.go index 87a12cb..b0be22d 100644 --- a/internal/web/render.go +++ b/internal/web/render.go @@ -30,12 +30,24 @@ type PageData struct { Flashes []Flash Alerts []Alert Version string + Asset string // cache-busting suffix for /static URLs; changes every build Now time.Time Data any Query url.Values BasePath string } +// assetVersion busts the browser cache for /static assets on every new +// build, so a redeploy is never masked by a day-old cached app.js. It falls +// back to the semantic version when no VCS commit was embedded (e.g. a build +// outside a git checkout), which is still stable within one running process. +var assetVersion = func() string { + if version.Commit != "" { + return version.Commit + } + return version.Version +}() + // Alert is a persistent banner such as "a restart is required". type Alert struct { Level string // warning, danger, info @@ -94,6 +106,7 @@ func (s *Server) render(w http.ResponseWriter, r *http.Request, page string, dat } data.Version = version.Version + data.Asset = assetVersion data.Now = time.Now() if data.Query == nil { data.Query = r.URL.Query() @@ -126,6 +139,7 @@ func (s *Server) renderError(w http.ResponseWriter, r *http.Request, status int, data := PageData{ Title: http.StatusText(status), Version: version.Version, + Asset: assetVersion, Now: time.Now(), Data: map[string]any{ "Status": status, diff --git a/internal/web/server.go b/internal/web/server.go index 12283c2..d00f36a 100644 --- a/internal/web/server.go +++ b/internal/web/server.go @@ -418,6 +418,7 @@ func (s *Server) withSecurityHeaders(next http.Handler) http.Handler { "font-src 'self'; "+ "connect-src 'self'; "+ "form-action 'self'; "+ + "frame-src 'self'; "+ "frame-ancestors 'none'; "+ "base-uri 'none'; "+ "object-src 'none'") diff --git a/web/templates/layout.html b/web/templates/layout.html index e161811..3b44604 100644 --- a/web/templates/layout.html +++ b/web/templates/layout.html @@ -8,7 +8,7 @@ - + @@ -119,7 +119,7 @@ - + {{block "scripts" .}}{{end}}