Skip to content

Commit f3e849e

Browse files
fileserver: Implement caddyfile.Unmarshaler interface (#5850)
1 parent f658fd0 commit f3e849e

File tree

1 file changed

+114
-85
lines changed

1 file changed

+114
-85
lines changed

modules/caddyhttp/fileserver/caddyfile.go

Lines changed: 114 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"github.com/caddyserver/caddy/v2"
2222
"github.com/caddyserver/caddy/v2/caddyconfig"
23+
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
2324
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
2425
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
2526
"github.com/caddyserver/caddy/v2/modules/caddyhttp/encode"
@@ -31,8 +32,23 @@ func init() {
3132
httpcaddyfile.RegisterDirective("try_files", parseTryFiles)
3233
}
3334

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:
3652
//
3753
// file_server [<matcher>] [browse] {
3854
// fs <filesystem>
@@ -44,103 +60,115 @@ func init() {
4460
// status <status>
4561
// disable_canonical_uris
4662
// }
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
4968

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()
6175
}
76+
fsrv.Browse = new(Browse)
77+
default:
78+
return d.ArgErr()
79+
}
6280

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()
7891

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+
}
8497

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+
}
89103

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+
}
96108

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)
117115

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)
121123
}
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)
127128
}
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)
134131
}
135-
fsrv.PassThru = true
132+
fsrv.PrecompressedRaw[d.Val()] = caddyconfig.JSON(precompress, nil)
133+
order = append(order, d.Val())
134+
}
135+
fsrv.PrecompressedOrder = order
136136

137-
default:
138-
return nil, h.Errf("unknown subdirective '%s'", h.Val())
137+
case "status":
138+
if !d.NextArg() {
139+
return d.ArgErr()
139140
}
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())
140158
}
141159
}
142160

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.
144172
if configFiles := h.Caddyfiles(); len(configFiles) > 0 {
145173
for _, file := range configFiles {
146174
file = filepath.Clean(file)
@@ -155,8 +183,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
155183
}
156184
}
157185
}
158-
159-
return &fsrv, nil
186+
return nil
160187
}
161188

162189
// parseTryFiles parses the try_files directive. It combines a file matcher
@@ -257,3 +284,5 @@ func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
257284

258285
return result, nil
259286
}
287+
288+
var _ caddyfile.Unmarshaler = (*FileServer)(nil)

0 commit comments

Comments
 (0)