feat(embed fs): enable conditional cache for go:embed files (#2299)

* feat(embed fs): add static assets 304 cache policy support

* optimize embed fs for cache policy support logic
pull/2308/head
北野 - Michael 2025-04-25 18:26:15 +08:00 committed by GitHub
parent d195002bf7
commit d8fc81d0eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 5 deletions

View File

@ -218,9 +218,10 @@ var (
type file struct {
// The compiler knows the layout of this struct.
// See cmd/compile/internal/staticdata's WriteEmbed.
name string
data string
hash [16]byte // truncated SHA256 hash
name string
data string
hash [16]byte // truncated SHA256 hash
modTime time.Time
}
var (
@ -230,7 +231,7 @@ var (
func (f *file) Name() string { _, elem, _ := split(f.name); return elem }
func (f *file) Size() int64 { return int64(len(f.data)) }
func (f *file) ModTime() time.Time { return time.Time{} }
func (f *file) ModTime() time.Time { return f.modTime }
func (f *file) IsDir() bool { _, _, isDir := split(f.name); return isDir }
func (f *file) Sys() any { return nil }
func (f *file) Type() fs.FileMode { return f.Mode().Type() }

View File

@ -4,15 +4,18 @@ import (
"archive/zip"
"bufio"
"crypto/sha256"
"debug/buildinfo"
_ "embed"
"encoding/json"
"fmt"
"io"
"io/fs"
"net/http"
"os"
"path/filepath"
"sort"
"strings"
"time"
"github.com/cloudreve/Cloudreve/v4/application/constants"
"github.com/cloudreve/Cloudreve/v4/pkg/logging"
@ -106,6 +109,7 @@ func NewStaticFS(l logging.Logger) fs.FS {
}
var files []file
modTime := getBuildTime()
err = fs.WalkDir(zipReader, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return fmt.Errorf("cannot walk into %q: %w", path, err)
@ -115,7 +119,7 @@ func NewStaticFS(l logging.Logger) fs.FS {
return nil
}
var f file
f := file{modTime: modTime}
if d.IsDir() {
f.name = path + "/"
} else {
@ -204,3 +208,24 @@ func Eject(l logging.Logger, statics fs.FS) error {
l.Info("Finish ejecting static resources.")
return nil
}
func getBuildTime() (buildTime time.Time) {
buildTime = time.Now()
exe, err := os.Executable()
if err != nil {
return
}
info, err := buildinfo.ReadFile(exe)
if err != nil {
return
}
for _, s := range info.Settings {
if s.Key == "vcs.time" && s.Value != "" {
if t, err := time.Parse(time.RFC3339, s.Value); err == nil {
buildTime = t
}
break
}
}
return
}