aboutsummaryrefslogtreecommitdiffhomepage
path: root/modules/caddyhttp/fileserver/staticfiles.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/caddyhttp/fileserver/staticfiles.go')
-rw-r--r--modules/caddyhttp/fileserver/staticfiles.go38
1 files changed, 37 insertions, 1 deletions
diff --git a/modules/caddyhttp/fileserver/staticfiles.go b/modules/caddyhttp/fileserver/staticfiles.go
index 57d1bc851..15ae35e38 100644
--- a/modules/caddyhttp/fileserver/staticfiles.go
+++ b/modules/caddyhttp/fileserver/staticfiles.go
@@ -161,6 +161,12 @@ type FileServer struct {
PrecompressedOrder []string `json:"precompressed_order,omitempty"`
precompressors map[string]encode.Precompressed
+ // List of file extensions to try to read Etags from.
+ // If set, file Etags will be read from sidecar files
+ // with any of these suffixes, instead of generating
+ // our own Etag.
+ EtagFileExtensions []string `json:"etag_file_extensions,omitempty"`
+
fsmap caddy.FileSystems
logger *zap.Logger
@@ -396,6 +402,14 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next c
w.Header().Del("Accept-Ranges")
w.Header().Add("Vary", "Accept-Encoding")
+ // try to get the etag from pre computed files if an etag suffix list was provided
+ if etag == "" && fsrv.EtagFileExtensions != nil {
+ etag, err = fsrv.getEtagFromFile(fileSystem, compressedFilename)
+ if err != nil {
+ return err
+ }
+ }
+
// don't assign info = compressedInfo because sidecars are kind
// of transparent; however we do need to set the Etag:
// https://caddy.community/t/gzipped-sidecar-file-wrong-same-etag/16793
@@ -420,7 +434,13 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next c
return err // error is already structured
}
defer file.Close()
-
+ // try to get the etag from pre computed files if an etag suffix list was provided
+ if etag == "" && fsrv.EtagFileExtensions != nil {
+ etag, err = fsrv.getEtagFromFile(fileSystem, filename)
+ if err != nil {
+ return err
+ }
+ }
if etag == "" {
etag = calculateEtag(info)
}
@@ -639,6 +659,22 @@ func calculateEtag(d os.FileInfo) string {
return `"` + t + s + `"`
}
+// Finds the first corresponding etag file for a given file in the file system and return its content
+func (fsrv *FileServer) getEtagFromFile(fileSystem fs.FS, filename string) (string, error) {
+ for _, suffix := range fsrv.EtagFileExtensions {
+ etagFilename := filename + suffix
+ etag, err := fs.ReadFile(fileSystem, etagFilename)
+ if errors.Is(err, fs.ErrNotExist) {
+ continue
+ }
+ if err != nil {
+ return "", fmt.Errorf("cannot read etag from file %s: %v", etagFilename, err)
+ }
+ return string(etag), nil
+ }
+ return "", nil
+}
+
// redirect performs a redirect to a given path. The 'toPath' parameter
// MUST be solely a path, and MUST NOT include a query.
func redirect(w http.ResponseWriter, r *http.Request, toPath string) error {