@marcel91200 / caddy Mirror · read-only / commits / f3e849e4
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 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)