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

@ -221,6 +221,7 @@ type file struct {
name string name string
data string data string
hash [16]byte // truncated SHA256 hash hash [16]byte // truncated SHA256 hash
modTime time.Time
} }
var ( var (
@ -230,7 +231,7 @@ var (
func (f *file) Name() string { _, elem, _ := split(f.name); return elem } func (f *file) Name() string { _, elem, _ := split(f.name); return elem }
func (f *file) Size() int64 { return int64(len(f.data)) } 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) IsDir() bool { _, _, isDir := split(f.name); return isDir }
func (f *file) Sys() any { return nil } func (f *file) Sys() any { return nil }
func (f *file) Type() fs.FileMode { return f.Mode().Type() } func (f *file) Type() fs.FileMode { return f.Mode().Type() }

View File

@ -4,15 +4,18 @@ import (
"archive/zip" "archive/zip"
"bufio" "bufio"
"crypto/sha256" "crypto/sha256"
"debug/buildinfo"
_ "embed" _ "embed"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"io/fs" "io/fs"
"net/http" "net/http"
"os"
"path/filepath" "path/filepath"
"sort" "sort"
"strings" "strings"
"time"
"github.com/cloudreve/Cloudreve/v4/application/constants" "github.com/cloudreve/Cloudreve/v4/application/constants"
"github.com/cloudreve/Cloudreve/v4/pkg/logging" "github.com/cloudreve/Cloudreve/v4/pkg/logging"
@ -106,6 +109,7 @@ func NewStaticFS(l logging.Logger) fs.FS {
} }
var files []file var files []file
modTime := getBuildTime()
err = fs.WalkDir(zipReader, ".", func(path string, d fs.DirEntry, err error) error { err = fs.WalkDir(zipReader, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil { if err != nil {
return fmt.Errorf("cannot walk into %q: %w", path, err) return fmt.Errorf("cannot walk into %q: %w", path, err)
@ -115,7 +119,7 @@ func NewStaticFS(l logging.Logger) fs.FS {
return nil return nil
} }
var f file f := file{modTime: modTime}
if d.IsDir() { if d.IsDir() {
f.name = path + "/" f.name = path + "/"
} else { } else {
@ -204,3 +208,24 @@ func Eject(l logging.Logger, statics fs.FS) error {
l.Info("Finish ejecting static resources.") l.Info("Finish ejecting static resources.")
return nil 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
}