diff options
author | Mike Crute <mike@crute.us> | 2023-08-17 07:49:29 -0700 |
---|---|---|
committer | Mike Crute <mike@crute.us> | 2023-08-17 07:49:29 -0700 |
commit | 9956e64f2c9f8c055c60bc82fcbb1e979bfb0b47 (patch) | |
tree | 8b572d85346fb327957c30aba587bc2016b48a9b | |
parent | fb4e88c5b1bec3c5d0e35b2c12561778b83f88c0 (diff) | |
download | golib-9956e64f2c9f8c055c60bc82fcbb1e979bfb0b47.tar.bz2 golib-9956e64f2c9f8c055c60bc82fcbb1e979bfb0b47.tar.xz golib-9956e64f2c9f8c055c60bc82fcbb1e979bfb0b47.zip |
echo: support etags for static filesecho/v0.9.5
-rw-r--r-- | echo/static_file.go | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/echo/static_file.go b/echo/static_file.go index 9723db7..258c832 100644 --- a/echo/static_file.go +++ b/echo/static_file.go | |||
@@ -1,6 +1,8 @@ | |||
1 | package echo | 1 | package echo |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "crypto/sha256" | ||
5 | "encoding/base64" | ||
4 | "io" | 6 | "io" |
5 | "io/fs" | 7 | "io/fs" |
6 | "net/http" | 8 | "net/http" |
@@ -12,7 +14,16 @@ import ( | |||
12 | 14 | ||
13 | type routeFunc func(string, echo.HandlerFunc, ...echo.MiddlewareFunc) *echo.Route | 15 | type routeFunc func(string, echo.HandlerFunc, ...echo.MiddlewareFunc) *echo.Route |
14 | 16 | ||
17 | func StaticFSSha256Etags(get routeFunc, f fs.FS, prefix, root string, m ...echo.MiddlewareFunc) *echo.Route { | ||
18 | return staticFS(get, f, prefix, root, true, m...) | ||
19 | } | ||
20 | |||
15 | func StaticFS(get routeFunc, f fs.FS, prefix, root string, m ...echo.MiddlewareFunc) *echo.Route { | 21 | func StaticFS(get routeFunc, f fs.FS, prefix, root string, m ...echo.MiddlewareFunc) *echo.Route { |
22 | return staticFS(get, f, prefix, root, false, m...) | ||
23 | } | ||
24 | |||
25 | // TODO: This should support HEAD requests | ||
26 | func staticFS(get routeFunc, f fs.FS, prefix, root string, addEtags bool, m ...echo.MiddlewareFunc) *echo.Route { | ||
16 | if root == "" { | 27 | if root == "" { |
17 | root = "." // For security we want to restrict to CWD. | 28 | root = "." // For security we want to restrict to CWD. |
18 | } | 29 | } |
@@ -52,6 +63,25 @@ func StaticFS(get routeFunc, f fs.FS, prefix, root string, m ...echo.MiddlewareF | |||
52 | return echo.ErrInternalServerError | 63 | return echo.ErrInternalServerError |
53 | } | 64 | } |
54 | 65 | ||
66 | // Only do this if the consumer requests it since it could be expensive | ||
67 | // for high traffic sites as it requires a full read and SHA256 | ||
68 | // computation | ||
69 | // TODO: Cache this? | ||
70 | if addEtags { | ||
71 | h := sha256.New() | ||
72 | if _, err := io.Copy(h, fs); err != nil { | ||
73 | c.Logger().Errorf("Error checksumming file %s: %s", p, err) | ||
74 | return echo.ErrInternalServerError | ||
75 | } | ||
76 | etag := base64.RawStdEncoding.EncodeToString(h.Sum(nil)) | ||
77 | c.Response().Header().Add("ETag", etag) | ||
78 | |||
79 | if _, err := fs.Seek(0, io.SeekStart); err != nil { | ||
80 | c.Logger().Errorf("Error seeking 0 in file %s: %s", p, err) | ||
81 | return echo.ErrInternalServerError | ||
82 | } | ||
83 | } | ||
84 | |||
55 | http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), fs) | 85 | http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), fs) |
56 | return nil | 86 | return nil |
57 | } | 87 | } |