123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- package util
- import (
- "embed"
- "errors"
- "io"
- "io/fs"
- "time"
- )
- // CachingEmbedFS is a wrapper around embed.FS that allows setting a ModTime, so that the
- // default static file server can send 304s back. It can be used like this:
- //
- // var (
- // //go:embed docs
- // docsStaticFs embed.FS
- // docsStaticCached = &util.CachingEmbedFS{ModTime: time.Now(), FS: docsStaticFs}
- // )
- //
- // http.FileServer(http.FS(docsStaticCached)).ServeHTTP(w, r)
- type CachingEmbedFS struct {
- ModTime time.Time
- FS embed.FS
- }
- // Open opens a file in the embedded filesystem and returns a fs.File with the static ModTime
- func (f CachingEmbedFS) Open(name string) (fs.File, error) {
- file, err := f.FS.Open(name)
- if err != nil {
- return nil, err
- }
- stat, err := file.Stat()
- if err != nil {
- return nil, err
- }
- return &cachingEmbedFile{file, f.ModTime, stat}, nil
- }
- type cachingEmbedFile struct {
- file fs.File
- modTime time.Time
- fs.FileInfo
- }
- func (f cachingEmbedFile) Stat() (fs.FileInfo, error) {
- return f, nil
- }
- func (f cachingEmbedFile) Read(bytes []byte) (int, error) {
- return f.file.Read(bytes)
- }
- func (f *cachingEmbedFile) Seek(offset int64, whence int) (int64, error) {
- if seeker, ok := f.file.(io.Seeker); ok {
- return seeker.Seek(offset, whence)
- }
- return 0, errors.New("io.Seeker not implemented")
- }
- func (f cachingEmbedFile) ModTime() time.Time {
- return f.modTime // We override this!
- }
- func (f cachingEmbedFile) Close() error {
- return f.file.Close()
- }
|