fix(ui): generate different ETag on file change
parent
211512da30
commit
a47845a390
ui
47
ui/dist.go
47
ui/dist.go
|
@ -1,12 +1,15 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"embed"
|
||||
"fmt"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -19,6 +22,7 @@ const (
|
|||
//go:embed build/*
|
||||
var embeddedFS embed.FS
|
||||
var buildDir fs.FS
|
||||
var fileETags sync.Map
|
||||
|
||||
//go:embed package.json
|
||||
var packageJson string
|
||||
|
@ -59,22 +63,34 @@ func (b *BindataAssets) Handler() http.Handler {
|
|||
}
|
||||
|
||||
// addCacheHeaders requests an hour of Cache-Control and sets an ETag based on file size and modtime
|
||||
func addCacheHeaders(file fs.File, headers http.Header) error {
|
||||
fi, err := file.Stat()
|
||||
if err == nil {
|
||||
headers.Add("Cache-Control", "public, max-age=3600")
|
||||
func addCacheHeaders(name string, headers http.Header) error {
|
||||
headers.Set("Cache-Control", "public, max-age=3600")
|
||||
headers.Set("X-Frame-Options", "SAMEORIGIN")
|
||||
headers.Set("X-XSS-Protection", "1; mode=block")
|
||||
headers.Set("X-Content-Type-Options", "nosniff")
|
||||
headers.Set("Content-Security-Policy", "script-src 'self'; object-src 'self'")
|
||||
|
||||
headers.Add("X-Frame-Options", "SAMEORIGIN")
|
||||
headers.Add("X-XSS-Protection", "1; mode=block")
|
||||
headers.Add("X-Content-Type-Options", "nosniff")
|
||||
headers.Add("Content-Security-Policy", "script-src 'self'; object-src 'self'")
|
||||
|
||||
hour, minute, second := fi.ModTime().Clock()
|
||||
etag := fmt.Sprintf(`"%d%d%d%d%d"`, fi.Size(), fi.ModTime().Day(), hour, minute, second)
|
||||
// go embed does not include real Stat().ModTime to make ETag computation simple
|
||||
// see https://github.com/golang/go/issues/43223
|
||||
// as a workaround, compute ETag from file contents cand cache it
|
||||
|
||||
if etag, found := fileETags.Load(name); found {
|
||||
headers.Set("ETag", etag.(string))
|
||||
return nil
|
||||
}
|
||||
// compute and store SHA1 digest of file contents as an ETag
|
||||
hash := sha1.New()
|
||||
if input, err := buildDir.Open(name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if _, err := io.Copy(hash, input); err != nil {
|
||||
return err
|
||||
}
|
||||
etag := base64.StdEncoding.EncodeToString(hash.Sum(nil))
|
||||
fileETags.Store(name, etag)
|
||||
headers.Set("ETag", etag)
|
||||
}
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
// ServeHTTP wraps http.FileServer by returning a default asset if the asset
|
||||
|
@ -98,13 +114,14 @@ func (b *BindataAssets) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
// Additionally, because we know we are returning the default asset,
|
||||
// we need to set the default asset's content-type.
|
||||
w.Header().Set("Content-Type", DefaultPageContentType)
|
||||
defaultFile, err := buildDir.Open(DefaultPage)
|
||||
name = DefaultPage
|
||||
defaultFile, err := buildDir.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file = defaultFile
|
||||
}
|
||||
if err := addCacheHeaders(file, w.Header()); err != nil {
|
||||
if err := addCacheHeaders(name, w.Header()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// https://github.com/influxdata/chronograf/issues/5565
|
||||
|
|
Loading…
Reference in New Issue