@marcel91200 / caddy Mirror · read-only / commits / f0216967
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 14, 05:15 UTC

caddyfile: Refactor unmarshaling of module tokens

Eliminates a fair amount of repeated code

Matthew Holt committed Jan 5, 2021 at 14:39 UTC f0216967dca12831b1aac351fc8c4bfcea148697
9 files changed +88 -139
caddyconfig/caddyfile/adapter.go
+26
@@ -94,5 +94,31 @@ type ServerType interface {
94 Setup([]ServerBlock, map[string]interface{}) (*caddy.Config, []caddyconfig.Warning, error)
95 }
96
97 +// UnmarshalModule instantiates a module with the given ID and invokes
98 +// UnmarshalCaddyfile on the new value using the immediate next segment
99 +// of d as input. In other words, d's next token should be the first
100 +// token of the module's Caddyfile input.
101 +//
102 +// This function is used when the next segment of Caddyfile tokens
103 +// belongs to another Caddy module. The returned value is often
104 +// type-asserted to the module's associated type for practical use
105 +// when setting up a config.
106 +func UnmarshalModule(d *Dispenser, moduleID string) (Unmarshaler, error) {
107 + mod, err := caddy.GetModule(moduleID)
108 + if err != nil {
109 + return nil, d.Errf("getting module named '%s': %v", moduleID, err)
110 + }
111 + inst := mod.New()
112 + unm, ok := inst.(Unmarshaler)
113 + if !ok {
114 + return nil, d.Errf("module %s is not a Caddyfile unmarshaler; is %T", mod.ID, inst)
115 + }
116 + err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
117 + if err != nil {
118 + return nil, err
119 + }
120 + return unm, nil
121 +}
122 +
123 // Interface guard
124 var _ caddyconfig.Adapter = (*Adapter)(nil)
caddyconfig/httpcaddyfile/builtins.go
+14 -40
@@ -285,21 +285,14 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
285 return nil, h.ArgErr()
286 }
287 modName := h.Val()
288 - mod, err := caddy.GetModule("tls.issuance." + modName)
289 - if err != nil {
290 - return nil, h.Errf("getting issuer module '%s': %v", modName, err)
291 - }
292 - unm, ok := mod.New().(caddyfile.Unmarshaler)
293 - if !ok {
294 - return nil, h.Errf("issuer module '%s' is not a Caddyfile unmarshaler", mod.ID)
295 - }
296 - err = unm.UnmarshalCaddyfile(h.NewFromNextSegment())
288 + modID := "tls.issuance." + modName
289 + unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
290 if err != nil {
291 return nil, err
292 }
293 issuer, ok := unm.(certmagic.Issuer)
294 if !ok {
302 - return nil, h.Errf("module %s is not a certmagic.Issuer", mod.ID)
295 + return nil, h.Errf("module %s (%T) is not a certmagic.Issuer", modID, unm)
296 }
297 issuers = append(issuers, issuer)
298
@@ -315,18 +308,12 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
308 acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
309 acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
310 }
318 - dnsProvModule, err := caddy.GetModule("dns.providers." + provName)
311 + modID := "dns.providers." + provName
312 + unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
313 if err != nil {
320 - return nil, h.Errf("getting DNS provider module named '%s': %v", provName, err)
321 - }
322 - dnsProvModuleInstance := dnsProvModule.New()
323 - if unm, ok := dnsProvModuleInstance.(caddyfile.Unmarshaler); ok {
324 - err = unm.UnmarshalCaddyfile(h.NewFromNextSegment())
325 - if err != nil {
326 - return nil, err
327 - }
314 + return nil, err
315 }
329 - acmeIssuer.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(dnsProvModuleInstance, "name", provName, h.warnings)
316 + acmeIssuer.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, h.warnings)
317
318 case "ca_root":
319 arg := h.RemainingArgs()
@@ -583,21 +570,15 @@ func parseLog(h Helper) ([]ConfigValue, error) {
570 case "discard":
571 wo = caddy.DiscardWriter{}
572 default:
586 - mod, err := caddy.GetModule("caddy.logging.writers." + moduleName)
587 - if err != nil {
588 - return nil, h.Errf("getting log writer module named '%s': %v", moduleName, err)
589 - }
590 - unm, ok := mod.New().(caddyfile.Unmarshaler)
591 - if !ok {
592 - return nil, h.Errf("log writer module '%s' is not a Caddyfile unmarshaler", mod)
593 - }
594 - err = unm.UnmarshalCaddyfile(h.NewFromNextSegment())
573 + modID := "caddy.logging.writers." + moduleName
574 + unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
575 if err != nil {
576 return nil, err
577 }
578 + var ok bool
579 wo, ok = unm.(caddy.WriterOpener)
580 if !ok {
600 - return nil, h.Errf("module %s is not a WriterOpener", mod)
581 + return nil, h.Errf("module %s (%T) is not a WriterOpener", modID, unm)
582 }
583 }
584 cl.WriterRaw = caddyconfig.JSONModuleObject(wo, "output", moduleName, h.warnings)
@@ -607,21 +588,14 @@ func parseLog(h Helper) ([]ConfigValue, error) {
588 return nil, h.ArgErr()
589 }
590 moduleName := h.Val()
610 - mod, err := caddy.GetModule("caddy.logging.encoders." + moduleName)
611 - if err != nil {
612 - return nil, h.Errf("getting log encoder module named '%s': %v", moduleName, err)
613 - }
614 - unm, ok := mod.New().(caddyfile.Unmarshaler)
615 - if !ok {
616 - return nil, h.Errf("log encoder module '%s' is not a Caddyfile unmarshaler", mod)
617 - }
618 - err = unm.UnmarshalCaddyfile(h.NewFromNextSegment())
591 + moduleID := "caddy.logging.encoders." + moduleName
592 + unm, err := caddyfile.UnmarshalModule(h.Dispenser, moduleID)
593 if err != nil {
594 return nil, err
595 }
596 enc, ok := unm.(zapcore.Encoder)
597 if !ok {
624 - return nil, h.Errf("module %s is not a zapcore.Encoder", mod)
598 + return nil, h.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
599 }
600 cl.EncoderRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, h.warnings)
601
caddyconfig/httpcaddyfile/options.go
+24 -21
@@ -34,7 +34,7 @@ func init() {
34 RegisterGlobalOption("storage", parseOptStorage)
35 RegisterGlobalOption("acme_ca", parseOptSingleString)
36 RegisterGlobalOption("acme_ca_root", parseOptSingleString)
37 - RegisterGlobalOption("acme_dns", parseOptSingleString)
37 + RegisterGlobalOption("acme_dns", parseOptACMEDNS)
38 RegisterGlobalOption("acme_eab", parseOptACMEEAB)
39 RegisterGlobalOption("cert_issuer", parseOptCertIssuer)
40 RegisterGlobalOption("email", parseOptSingleString)
@@ -165,24 +165,35 @@ func parseOptStorage(d *caddyfile.Dispenser) (interface{}, error) {
165 if !d.Next() { // get storage module name
166 return nil, d.ArgErr()
167 }
168 - modName := d.Val()
169 - mod, err := caddy.GetModule("caddy.storage." + modName)
168 + modID := "caddy.storage." + d.Val()
169 + unm, err := caddyfile.UnmarshalModule(d, modID)
170 if err != nil {
171 - return nil, d.Errf("getting storage module '%s': %v", modName, err)
171 + return nil, err
172 }
173 - unm, ok := mod.New().(caddyfile.Unmarshaler)
173 + storage, ok := unm.(caddy.StorageConverter)
174 if !ok {
175 - return nil, d.Errf("storage module '%s' is not a Caddyfile unmarshaler", mod.ID)
175 + return nil, d.Errf("module %s is not a caddy.StorageConverter", modID)
176 + }
177 + return storage, nil
178 +}
179 +
180 +func parseOptACMEDNS(d *caddyfile.Dispenser) (interface{}, error) {
181 + if !d.Next() { // consume option name
182 + return nil, d.ArgErr()
183 }
177 - err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
184 + if !d.Next() { // get DNS module name
185 + return nil, d.ArgErr()
186 + }
187 + modID := "dns.providers." + d.Val()
188 + unm, err := caddyfile.UnmarshalModule(d, modID)
189 if err != nil {
190 return nil, err
191 }
181 - storage, ok := unm.(caddy.StorageConverter)
192 + prov, ok := unm.(certmagic.ACMEDNSProvider)
193 if !ok {
183 - return nil, d.Errf("module %s is not a StorageConverter", mod.ID)
194 + return nil, d.Errf("module %s (%T) is not a certmagic.ACMEDNSProvider", modID, unm)
195 }
185 - return storage, nil
196 + return prov, nil
197 }
198
199 func parseOptACMEEAB(d *caddyfile.Dispenser) (interface{}, error) {
@@ -220,22 +231,14 @@ func parseOptCertIssuer(d *caddyfile.Dispenser) (interface{}, error) {
231 if !d.Next() { // get issuer module name
232 return nil, d.ArgErr()
233 }
223 - modName := d.Val()
224 - mod, err := caddy.GetModule("tls.issuance." + modName)
225 - if err != nil {
226 - return nil, d.Errf("getting issuer module '%s': %v", modName, err)
227 - }
228 - unm, ok := mod.New().(caddyfile.Unmarshaler)
229 - if !ok {
230 - return nil, d.Errf("issuer module '%s' is not a Caddyfile unmarshaler", mod.ID)
231 - }
232 - err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
234 + modID := "tls.issuance." + d.Val()
235 + unm, err := caddyfile.UnmarshalModule(d, modID)
236 if err != nil {
237 return nil, err
238 }
239 iss, ok := unm.(certmagic.Issuer)
240 if !ok {
238 - return nil, d.Errf("module %s is not a certmagic.Issuer", mod.ID)
241 + return nil, d.Errf("module %s (%T) is not a certmagic.Issuer", modID, unm)
242 }
243 return iss, nil
244 }
caddyconfig/httpcaddyfile/serveroptions.go
+3 -10
@@ -57,21 +57,14 @@ func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (interface{}, error
57 switch d.Val() {
58 case "listener_wrappers":
59 for nesting := d.Nesting(); d.NextBlock(nesting); {
60 - mod, err := caddy.GetModule("caddy.listeners." + d.Val())
61 - if err != nil {
62 - return nil, fmt.Errorf("finding listener module '%s': %v", d.Val(), err)
63 - }
64 - unm, ok := mod.New().(caddyfile.Unmarshaler)
65 - if !ok {
66 - return nil, fmt.Errorf("listener module '%s' is not a Caddyfile unmarshaler", mod)
67 - }
68 - err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
60 + modID := "caddy.listeners." + d.Val()
61 + unm, err := caddyfile.UnmarshalModule(d, modID)
62 if err != nil {
63 return nil, err
64 }
65 listenerWrapper, ok := unm.(caddy.ListenerWrapper)
66 if !ok {
74 - return nil, fmt.Errorf("module %s is not a listener wrapper", mod)
67 + return nil, fmt.Errorf("module %s (%T) is not a listener wrapper", modID, unm)
68 }
69 jsonListenerWrapper := caddyconfig.JSONModuleObject(
70 listenerWrapper,
caddyconfig/httpcaddyfile/tlsapp.go
+1 -6
@@ -392,14 +392,9 @@ func fillInGlobalACMEDefaults(issuer certmagic.Issuer, options map[string]interf
392 acmeIssuer.TrustedRootsPEMFiles = append(acmeIssuer.TrustedRootsPEMFiles, globalACMECARoot.(string))
393 }
394 if globalACMEDNS != nil && (acmeIssuer.Challenges == nil || acmeIssuer.Challenges.DNS == nil) {
395 - provName := globalACMEDNS.(string)
396 - dnsProvModule, err := caddy.GetModule("dns.providers." + provName)
397 - if err != nil {
398 - return fmt.Errorf("getting DNS provider module named '%s': %v", provName, err)
399 - }
395 acmeIssuer.Challenges = &caddytls.ChallengesConfig{
396 DNS: &caddytls.DNSChallengeConfig{
402 - ProviderRaw: caddyconfig.JSONModuleObject(dnsProvModule.New(), "name", provName, nil),
397 + ProviderRaw: caddyconfig.JSONModuleObject(globalACMEDNS, "name", globalACMEDNS.(caddy.Module).CaddyModule().ID.Name(), nil),
398 },
399 }
400 }
modules/caddyhttp/encode/caddyfile.go
+3 -10
@@ -64,21 +64,14 @@ func (enc *Encode) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
64
65 for d.NextBlock(0) {
66 name := d.Val()
67 - mod, err := caddy.GetModule("http.encoders." + name)
68 - if err != nil {
69 - return fmt.Errorf("getting encoder module '%s': %v", name, err)
70 - }
71 - unm, ok := mod.New().(caddyfile.Unmarshaler)
72 - if !ok {
73 - return fmt.Errorf("encoder module '%s' is not a Caddyfile unmarshaler", mod)
74 - }
75 - err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
67 + modID := "http.encoders." + name
68 + unm, err := caddyfile.UnmarshalModule(d, modID)
69 if err != nil {
70 return err
71 }
72 encoding, ok := unm.(Encoding)
73 if !ok {
81 - return fmt.Errorf("module %s is not an HTTP encoding", mod)
74 + return fmt.Errorf("module %s is not an HTTP encoding; is %T", modID, unm)
75 }
76 if enc.EncodingsRaw == nil {
77 enc.EncodingsRaw = make(caddy.ModuleMap)
modules/caddyhttp/reverseproxy/caddyfile.go
+6 -20
@@ -241,21 +241,14 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
241 return d.Err("load balancing selection policy already specified")
242 }
243 name := d.Val()
244 - mod, err := caddy.GetModule("http.reverse_proxy.selection_policies." + name)
245 - if err != nil {
246 - return d.Errf("getting load balancing policy module '%s': %v", mod, err)
247 - }
248 - unm, ok := mod.New().(caddyfile.Unmarshaler)
249 - if !ok {
250 - return d.Errf("load balancing policy module '%s' is not a Caddyfile unmarshaler", mod)
251 - }
252 - err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
244 + modID := "http.reverse_proxy.selection_policies." + name
245 + unm, err := caddyfile.UnmarshalModule(d, modID)
246 if err != nil {
247 return err
248 }
249 sel, ok := unm.(Selector)
250 if !ok {
258 - return d.Errf("module %s is not a Selector", mod)
251 + return d.Errf("module %s (%T) is not a reverseproxy.Selector", modID, unm)
252 }
253 if h.LoadBalancing == nil {
254 h.LoadBalancing = new(LoadBalancing)
@@ -574,21 +567,14 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
567 return d.Err("transport already specified")
568 }
569 transportModuleName = d.Val()
577 - mod, err := caddy.GetModule("http.reverse_proxy.transport." + transportModuleName)
578 - if err != nil {
579 - return d.Errf("getting transport module '%s': %v", mod, err)
580 - }
581 - unm, ok := mod.New().(caddyfile.Unmarshaler)
582 - if !ok {
583 - return d.Errf("transport module '%s' is not a Caddyfile unmarshaler", mod)
584 - }
585 - err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
570 + modID := "http.reverse_proxy.transport." + transportModuleName
571 + unm, err := caddyfile.UnmarshalModule(d, modID)
572 if err != nil {
573 return err
574 }
575 rt, ok := unm.(http.RoundTripper)
576 if !ok {
591 - return d.Errf("module %s is not a RoundTripper", mod)
577 + return d.Errf("module %s (%T) is not a RoundTripper", modID, unm)
578 }
579 transport = rt
580
modules/caddytls/acmeissuer.go
+3 -10
@@ -354,18 +354,11 @@ func (iss *ACMEIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
354 if iss.Challenges.DNS == nil {
355 iss.Challenges.DNS = new(DNSChallengeConfig)
356 }
357 - dnsProvModule, err := caddy.GetModule("dns.providers." + provName)
357 + unm, err := caddyfile.UnmarshalModule(d, "dns.providers."+provName)
358 if err != nil {
359 - return d.Errf("getting DNS provider module named '%s': %v", provName, err)
359 + return err
360 }
361 - dnsProvModuleInstance := dnsProvModule.New()
362 - if unm, ok := dnsProvModuleInstance.(caddyfile.Unmarshaler); ok {
363 - err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
364 - if err != nil {
365 - return err
366 - }
367 - }
368 - iss.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(dnsProvModuleInstance, "name", provName, nil)
361 + iss.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, nil)
362
363 case "resolvers":
364 if iss.Challenges == nil {
modules/logging/filterencoder.go
+8 -22
@@ -115,21 +115,14 @@ func (fe *FilterEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
115 return d.ArgErr()
116 }
117 moduleName := d.Val()
118 - mod, err := caddy.GetModule("caddy.logging.encoders." + moduleName)
119 - if err != nil {
120 - return d.Errf("getting log encoder module named '%s': %v", moduleName, err)
121 - }
122 - unm, ok := mod.New().(caddyfile.Unmarshaler)
123 - if !ok {
124 - return d.Errf("log encoder module '%s' is not a Caddyfile unmarshaler", mod)
125 - }
126 - err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
118 + moduleID := "caddy.logging.encoders." + moduleName
119 + unm, err := caddyfile.UnmarshalModule(d, moduleID)
120 if err != nil {
121 return err
122 }
123 enc, ok := unm.(zapcore.Encoder)
124 if !ok {
132 - return d.Errf("module %s is not a zapcore.Encoder", mod)
125 + return d.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
126 }
127 fe.WrappedRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, nil)
128
@@ -140,26 +133,19 @@ func (fe *FilterEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
133 return d.ArgErr()
134 }
135 filterName := d.Val()
143 - mod, err := caddy.GetModule("caddy.logging.encoders.filter." + filterName)
144 - if err != nil {
145 - return d.Errf("getting log filter module named '%s': %v", filterName, err)
146 - }
147 - unm, ok := mod.New().(caddyfile.Unmarshaler)
148 - if !ok {
149 - return d.Errf("log encoder module '%s' is not a Caddyfile unmarshaler", mod)
150 - }
151 - err = unm.UnmarshalCaddyfile(d.NewFromNextSegment())
136 + moduleID := "caddy.logging.encoders.filter." + filterName
137 + unm, err := caddyfile.UnmarshalModule(d, moduleID)
138 if err != nil {
139 return err
140 }
155 - f, ok := unm.(LogFieldFilter)
141 + filter, ok := unm.(LogFieldFilter)
142 if !ok {
157 - return d.Errf("module %s is not a LogFieldFilter", mod)
143 + return d.Errf("module %s (%T) is not a logging.LogFieldFilter", moduleID, unm)
144 }
145 if fe.FieldsRaw == nil {
146 fe.FieldsRaw = make(map[string]json.RawMessage)
147 }
162 - fe.FieldsRaw[field] = caddyconfig.JSONModuleObject(f, "filter", filterName, nil)
148 + fe.FieldsRaw[field] = caddyconfig.JSONModuleObject(filter, "filter", filterName, nil)
149 }
150
151 default: