diff options
author | Alan Pearce | 2024-05-30 13:54:29 +0200 |
---|---|---|
committer | Alan Pearce | 2024-05-30 13:54:29 +0200 |
commit | 4698a97974ae82e7bd8592828c58294b222a58ff (patch) | |
tree | fc7d6357534efffc69301fb01c6e04143288dbec /frontend/assets.go | |
parent | b02076363f979daa6ac313058eb140d1d67ce184 (diff) | |
download | searchix-4698a97974ae82e7bd8592828c58294b222a58ff.tar.lz searchix-4698a97974ae82e7bd8592828c58294b222a58ff.tar.zst searchix-4698a97974ae82e7bd8592828c58294b222a58ff.zip |
feat: enable sub-resource integrity for assets
Diffstat (limited to 'frontend/assets.go')
-rw-r--r-- | frontend/assets.go | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/frontend/assets.go b/frontend/assets.go new file mode 100644 index 0000000..a6a5e79 --- /dev/null +++ b/frontend/assets.go @@ -0,0 +1,95 @@ +package frontend + +import ( + "crypto/sha256" + "encoding/base64" + "io" + "io/fs" + "net/url" + + "github.com/pkg/errors" +) + +var Assets = AssetCollection{ + Scripts: make(map[string]Asset), + Stylesheets: make(map[string]Asset), +} + +type Asset struct { + URL string + Base64SHA256 string +} + +type AssetCollection struct { + Scripts map[string]Asset + Stylesheets map[string]Asset +} + +func hashFile(filename string) ([]byte, error) { + file, err := Files.Open(filename) + if err != nil { + return nil, errors.WithMessagef(err, "could not open file %s", filename) + } + sum := sha256.New() + defer file.Close() + if _, err := io.Copy(sum, file); err != nil { + return nil, errors.WithMessagef(err, "could not hash file %s", filename) + } + + return sum.Sum(nil), nil +} + +func newAsset(filename string, hash []byte) Asset { + u, err := url.JoinPath("/", filename) + if err != nil { + panic(err) + } + + return Asset{ + URL: u, + Base64SHA256: base64.StdEncoding.EncodeToString(hash), + } +} + +func hashScripts() error { + scripts, err := fs.Glob(Files, "static/**.js") + if err != nil { + return errors.WithMessage(err, "could not glob files") + } + for _, filename := range scripts { + hash, err := hashFile(filename) + if err != nil { + return err + } + Assets.Scripts[filename] = newAsset(filename, hash) + } + + return nil +} + +func hashStyles() error { + styles, err := fs.Glob(Files, "static/**.css") + if err != nil { + return errors.WithMessage(err, "could not glob files") + } + for _, filename := range styles { + hash, err := hashFile(filename) + if err != nil { + return err + } + Assets.Stylesheets[filename] = newAsset(filename, hash) + } + + return nil +} + +func init() { + err := hashScripts() + if err != nil { + panic(err) + } + err = hashStyles() + if err != nil { + panic(err) + } +} |