Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 12, 18:15 UTC
fileserver: Implement caddyfile.Unmarshaler interface (#5850)
Francis Lavoie committed
Jan 13, 2024 at 16:32 UTC
f3e849e49fb82f53ed1491269db5a509f2486168
1 file changed
+114
-85
modules/caddyhttp/fileserver/caddyfile.go
+114
-85
@@ -20,6 +20,7 @@ import (
20
21
"github.com/caddyserver/caddy/v2"
22
"github.com/caddyserver/caddy/v2/caddyconfig"
23
+ "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
24
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
25
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
26
"github.com/caddyserver/caddy/v2/modules/caddyhttp/encode"
@@ -31,8 +32,23 @@ func init() {
32
httpcaddyfile.RegisterDirective("try_files", parseTryFiles)
33
}
34
34
-// parseCaddyfile parses the file_server directive. It enables the static file
35
-// server and configures it with this syntax:
35
+// parseCaddyfile parses the file_server directive.
36
+// See UnmarshalCaddyfile for the syntax.
37
+func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
38
+ fsrv := new(FileServer)
39
+ err := fsrv.UnmarshalCaddyfile(h.Dispenser)
40
+ if err != nil {
41
+ return fsrv, err
42
+ }
43
+ err = fsrv.FinalizeUnmarshalCaddyfile(h)
44
+ if err != nil {
45
+ return nil, err
46
+ }
47
+ return fsrv, err
48
+}
49
+
50
+// UnmarshalCaddyfile parses the file_server directive. It enables
51
+// the static file server and configures it with this syntax:
52
//
53
// file_server [<matcher>] [browse] {
54
// fs <filesystem>
@@ -44,103 +60,115 @@ func init() {
60
// status <status>
61
// disable_canonical_uris
62
// }
47
-func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
48
- var fsrv FileServer
63
+//
64
+// The FinalizeUnmarshalCaddyfile method should be called after this
65
+// to finalize setup of hidden Caddyfiles.
66
+func (fsrv *FileServer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
67
+ d.Next() // consume directive name
68
50
- for h.Next() {
51
- args := h.RemainingArgs()
52
- switch len(args) {
53
- case 0:
54
- case 1:
55
- if args[0] != "browse" {
56
- return nil, h.ArgErr()
57
- }
58
- fsrv.Browse = new(Browse)
59
- default:
60
- return nil, h.ArgErr()
69
+ args := d.RemainingArgs()
70
+ switch len(args) {
71
+ case 0:
72
+ case 1:
73
+ if args[0] != "browse" {
74
+ return d.ArgErr()
75
}
76
+ fsrv.Browse = new(Browse)
77
+ default:
78
+ return d.ArgErr()
79
+ }
80
63
- for h.NextBlock(0) {
64
- switch h.Val() {
65
- case "fs":
66
- if !h.NextArg() {
67
- return nil, h.ArgErr()
68
- }
69
- if fsrv.FileSystem != "" {
70
- return nil, h.Err("file system already specified")
71
- }
72
- fsrv.FileSystem = h.Val()
73
- case "hide":
74
- fsrv.Hide = h.RemainingArgs()
75
- if len(fsrv.Hide) == 0 {
76
- return nil, h.ArgErr()
77
- }
81
+ for d.NextBlock(0) {
82
+ switch d.Val() {
83
+ case "fs":
84
+ if !d.NextArg() {
85
+ return d.ArgErr()
86
+ }
87
+ if fsrv.FileSystem != "" {
88
+ return d.Err("file system already specified")
89
+ }
90
+ fsrv.FileSystem = d.Val()
91
79
- case "index":
80
- fsrv.IndexNames = h.RemainingArgs()
81
- if len(fsrv.IndexNames) == 0 {
82
- return nil, h.ArgErr()
83
- }
92
+ case "hide":
93
+ fsrv.Hide = d.RemainingArgs()
94
+ if len(fsrv.Hide) == 0 {
95
+ return d.ArgErr()
96
+ }
97
85
- case "root":
86
- if !h.Args(&fsrv.Root) {
87
- return nil, h.ArgErr()
88
- }
98
+ case "index":
99
+ fsrv.IndexNames = d.RemainingArgs()
100
+ if len(fsrv.IndexNames) == 0 {
101
+ return d.ArgErr()
102
+ }
103
90
- case "browse":
91
- if fsrv.Browse != nil {
92
- return nil, h.Err("browsing is already configured")
93
- }
94
- fsrv.Browse = new(Browse)
95
- h.Args(&fsrv.Browse.TemplateFile)
104
+ case "root":
105
+ if !d.Args(&fsrv.Root) {
106
+ return d.ArgErr()
107
+ }
108
97
- case "precompressed":
98
- var order []string
99
- for h.NextArg() {
100
- modID := "http.precompressed." + h.Val()
101
- mod, err := caddy.GetModule(modID)
102
- if err != nil {
103
- return nil, h.Errf("getting module named '%s': %v", modID, err)
104
- }
105
- inst := mod.New()
106
- precompress, ok := inst.(encode.Precompressed)
107
- if !ok {
108
- return nil, h.Errf("module %s is not a precompressor; is %T", modID, inst)
109
- }
110
- if fsrv.PrecompressedRaw == nil {
111
- fsrv.PrecompressedRaw = make(caddy.ModuleMap)
112
- }
113
- fsrv.PrecompressedRaw[h.Val()] = caddyconfig.JSON(precompress, nil)
114
- order = append(order, h.Val())
115
- }
116
- fsrv.PrecompressedOrder = order
109
+ case "browse":
110
+ if fsrv.Browse != nil {
111
+ return d.Err("browsing is already configured")
112
+ }
113
+ fsrv.Browse = new(Browse)
114
+ d.Args(&fsrv.Browse.TemplateFile)
115
118
- case "status":
119
- if !h.NextArg() {
120
- return nil, h.ArgErr()
116
+ case "precompressed":
117
+ var order []string
118
+ for d.NextArg() {
119
+ modID := "http.precompressed." + d.Val()
120
+ mod, err := caddy.GetModule(modID)
121
+ if err != nil {
122
+ return d.Errf("getting module named '%s': %v", modID, err)
123
}
122
- fsrv.StatusCode = caddyhttp.WeakString(h.Val())
123
-
124
- case "disable_canonical_uris":
125
- if h.NextArg() {
126
- return nil, h.ArgErr()
124
+ inst := mod.New()
125
+ precompress, ok := inst.(encode.Precompressed)
126
+ if !ok {
127
+ return d.Errf("module %s is not a precompressor; is %T", modID, inst)
128
}
128
- falseBool := false
129
- fsrv.CanonicalURIs = &falseBool
130
-
131
- case "pass_thru":
132
- if h.NextArg() {
133
- return nil, h.ArgErr()
129
+ if fsrv.PrecompressedRaw == nil {
130
+ fsrv.PrecompressedRaw = make(caddy.ModuleMap)
131
}
135
- fsrv.PassThru = true
132
+ fsrv.PrecompressedRaw[d.Val()] = caddyconfig.JSON(precompress, nil)
133
+ order = append(order, d.Val())
134
+ }
135
+ fsrv.PrecompressedOrder = order
136
137
- default:
138
- return nil, h.Errf("unknown subdirective '%s'", h.Val())
137
+ case "status":
138
+ if !d.NextArg() {
139
+ return d.ArgErr()
140
}
141
+ fsrv.StatusCode = caddyhttp.WeakString(d.Val())
142
+
143
+ case "disable_canonical_uris":
144
+ if d.NextArg() {
145
+ return d.ArgErr()
146
+ }
147
+ falseBool := false
148
+ fsrv.CanonicalURIs = &falseBool
149
+
150
+ case "pass_thru":
151
+ if d.NextArg() {
152
+ return d.ArgErr()
153
+ }
154
+ fsrv.PassThru = true
155
+
156
+ default:
157
+ return d.Errf("unknown subdirective '%s'", d.Val())
158
}
159
}
160
143
- // hide the Caddyfile (and any imported Caddyfiles)
161
+ return nil
162
+}
163
+
164
+// FinalizeUnmarshalCaddyfile finalizes the Caddyfile parsing which
165
+// requires having an httpcaddyfile.Helper to function, to setup hidden Caddyfiles.
166
+func (fsrv *FileServer) FinalizeUnmarshalCaddyfile(h httpcaddyfile.Helper) error {
167
+ // Hide the Caddyfile (and any imported Caddyfiles).
168
+ // This needs to be done in here instead of UnmarshalCaddyfile
169
+ // because UnmarshalCaddyfile only has access to the dispenser
170
+ // and not the helper, and only the helper has access to the
171
+ // Caddyfiles function.
172
if configFiles := h.Caddyfiles(); len(configFiles) > 0 {
173
for _, file := range configFiles {
174
file = filepath.Clean(file)
@@ -155,8 +183,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
183
}
184
}
185
}
158
-
159
- return &fsrv, nil
186
+ return nil
187
}
188
189
// parseTryFiles parses the try_files directive. It combines a file matcher
@@ -257,3 +284,5 @@ func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
284
285
return result, nil
286
}
287
+
288
+var _ caddyfile.Unmarshaler = (*FileServer)(nil)