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: