@marcel91200 / caddy Mirror · read-only
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 01:00 UTC

master
go 90 lines 2.38 KB
Raw
1 package filesystems
2
3 import (
4 "io/fs"
5 "strings"
6 "sync"
7 )
8
9 const (
10 DefaultFileSystemKey = "default"
11 )
12
13 var DefaultFileSystem = &wrapperFs{key: DefaultFileSystemKey, FS: OsFS{}}
14
15 // wrapperFs exists so can easily add to wrapperFs down the line
16 type wrapperFs struct {
17 key string
18 fs.FS
19 }
20
21 // Embedding fs.FS hides the wrapped FS's optional interfaces, so forward them.
22 // Not GlobFS: OsFS.Glob uses filepath.Glob, whose semantics differ from fs.Glob.
23
24 func (w *wrapperFs) Stat(name string) (fs.FileInfo, error) { return fs.Stat(w.FS, name) }
25 func (w *wrapperFs) ReadDir(name string) ([]fs.DirEntry, error) { return fs.ReadDir(w.FS, name) }
26 func (w *wrapperFs) ReadFile(name string) ([]byte, error) { return fs.ReadFile(w.FS, name) }
27
28 var (
29 _ fs.StatFS = (*wrapperFs)(nil)
30 _ fs.ReadDirFS = (*wrapperFs)(nil)
31 _ fs.ReadFileFS = (*wrapperFs)(nil)
32 )
33
34 // FileSystemMap stores a map of filesystems
35 // the empty key will be overwritten to be the default key
36 // it includes a default filesystem, based off the os fs
37 type FileSystemMap struct {
38 m sync.Map
39 }
40
41 // note that the first invocation of key cannot be called in a racy context.
42 func (f *FileSystemMap) key(k string) string {
43 if k == "" {
44 k = DefaultFileSystemKey
45 }
46 return k
47 }
48
49 // Register will add the filesystem with key to later be retrieved
50 // A call with a nil fs will call unregister, ensuring that a call to Default() will never be nil
51 func (f *FileSystemMap) Register(k string, v fs.FS) {
52 k = f.key(k)
53 if v == nil {
54 f.Unregister(k)
55 return
56 }
57 f.m.Store(k, &wrapperFs{key: k, FS: v})
58 }
59
60 // Unregister will remove the filesystem with key from the filesystem map
61 // if the key is the default key, it will set the default to the osFS instead of deleting it
62 // modules should call this on cleanup to be safe
63 func (f *FileSystemMap) Unregister(k string) {
64 k = f.key(k)
65 if k == DefaultFileSystemKey {
66 f.m.Store(k, DefaultFileSystem)
67 } else {
68 f.m.Delete(k)
69 }
70 }
71
72 // Get will get a filesystem with a given key
73 func (f *FileSystemMap) Get(k string) (v fs.FS, ok bool) {
74 k = f.key(k)
75 c, ok := f.m.Load(strings.TrimSpace(k))
76 if !ok {
77 if k == DefaultFileSystemKey {
78 f.m.Store(k, DefaultFileSystem)
79 return DefaultFileSystem, true
80 }
81 return nil, ok
82 }
83 return c.(fs.FS), true
84 }
85
86 // Default will get the default filesystem in the filesystem map
87 func (f *FileSystemMap) Default() fs.FS {
88 val, _ := f.Get(DefaultFileSystemKey)
89 return val
90 }