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
caddyfile: Normalize & flatten all unmarshalers (#6037)
Francis Lavoie committed
Jan 23, 2024 at 19:36 UTC
750d0b83319ac0ea6b7f057b8270c19404c3d6fa
44 files changed
+2887
-2874
caddyconfig/caddyfile/adapter.go
+14
-18
@@ -92,30 +92,26 @@ func FormattingDifference(filename string, body []byte) (caddyconfig.Warning, bo
92
}, true
93
}
94
95
-// Unmarshaler is a type that can unmarshal
96
-// Caddyfile tokens to set itself up for a
97
-// JSON encoding. The goal of an unmarshaler
98
-// is not to set itself up for actual use,
99
-// but to set itself up for being marshaled
100
-// into JSON. Caddyfile-unmarshaled values
101
-// will not be used directly; they will be
102
-// encoded as JSON and then used from that.
103
-// Implementations must be able to support
104
-// multiple segments (instances of their
105
-// directive or batch of tokens); typically
106
-// this means wrapping all token logic in
107
-// a loop: `for d.Next() { ... }`.
95
+// Unmarshaler is a type that can unmarshal Caddyfile tokens to
96
+// set itself up for a JSON encoding. The goal of an unmarshaler
97
+// is not to set itself up for actual use, but to set itself up for
98
+// being marshaled into JSON. Caddyfile-unmarshaled values will not
99
+// be used directly; they will be encoded as JSON and then used from
100
+// that. Implementations _may_ be able to support multiple segments
101
+// (instances of their directive or batch of tokens); typically this
102
+// means wrapping parsing logic in a loop: `for d.Next() { ... }`.
103
+// More commonly, only a single segment is supported, so a simple
104
+// `d.Next()` at the start should be used to consume the module
105
+// identifier token (directive name, etc).
106
type Unmarshaler interface {
107
UnmarshalCaddyfile(d *Dispenser) error
108
}
109
110
// ServerType is a type that can evaluate a Caddyfile and set up a caddy config.
111
type ServerType interface {
114
- // Setup takes the server blocks which
115
- // contain tokens, as well as options
116
- // (e.g. CLI flags) and creates a Caddy
117
- // config, along with any warnings or
118
- // an error.
112
+ // Setup takes the server blocks which contain tokens,
113
+ // as well as options (e.g. CLI flags) and creates a
114
+ // Caddy config, along with any warnings or an error.
115
Setup([]ServerBlock, map[string]any) (*caddy.Config, []caddyconfig.Warning, error)
116
}
117
caddyconfig/httpcaddyfile/builtins.go
+534
-552
@@ -59,11 +59,8 @@ func init() {
59
//
60
// bind <addresses...>
61
func parseBind(h Helper) ([]ConfigValue, error) {
62
- var lnHosts []string
63
- for h.Next() {
64
- lnHosts = append(lnHosts, h.RemainingArgs()...)
65
- }
66
- return h.NewBindAddresses(lnHosts), nil
62
+ h.Next() // consume directive name
63
+ return []ConfigValue{{Class: "bind", Value: h.RemainingArgs()}}, nil
64
}
65
66
// parseTLS parses the tls directive. Syntax:
@@ -98,6 +95,8 @@ func parseBind(h Helper) ([]ConfigValue, error) {
95
// insecure_secrets_log <log_file>
96
// }
97
func parseTLS(h Helper) ([]ConfigValue, error) {
98
+ h.Next() // consume directive name
99
+
100
cp := new(caddytls.ConnectionPolicy)
101
var fileLoader caddytls.FileLoader
102
var folderLoader caddytls.FolderLoader
@@ -110,423 +109,421 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
109
var onDemand bool
110
var reusePrivateKeys bool
111
113
- for h.Next() {
114
- // file certificate loader
115
- firstLine := h.RemainingArgs()
116
- switch len(firstLine) {
117
- case 0:
118
- case 1:
119
- if firstLine[0] == "internal" {
120
- internalIssuer = new(caddytls.InternalIssuer)
121
- } else if !strings.Contains(firstLine[0], "@") {
122
- return nil, h.Err("single argument must either be 'internal' or an email address")
123
- } else {
124
- if acmeIssuer == nil {
125
- acmeIssuer = new(caddytls.ACMEIssuer)
126
- }
127
- acmeIssuer.Email = firstLine[0]
128
- }
129
-
130
- case 2:
131
- certFilename := firstLine[0]
132
- keyFilename := firstLine[1]
133
-
134
- // tag this certificate so if multiple certs match, specifically
135
- // this one that the user has provided will be used, see #2588:
136
- // https://github.com/caddyserver/caddy/issues/2588 ... but we
137
- // must be careful about how we do this; being careless will
138
- // lead to failed handshakes
139
- //
140
- // we need to remember which cert files we've seen, since we
141
- // must load each cert only once; otherwise, they each get a
142
- // different tag... since a cert loaded twice has the same
143
- // bytes, it will overwrite the first one in the cache, and
144
- // only the last cert (and its tag) will survive, so any conn
145
- // policy that is looking for any tag other than the last one
146
- // to be loaded won't find it, and TLS handshakes will fail
147
- // (see end of issue #3004)
148
- //
149
- // tlsCertTags maps certificate filenames to their tag.
150
- // This is used to remember which tag is used for each
151
- // certificate files, since we need to avoid loading
152
- // the same certificate files more than once, overwriting
153
- // previous tags
154
- tlsCertTags, ok := h.State["tlsCertTags"].(map[string]string)
155
- if !ok {
156
- tlsCertTags = make(map[string]string)
157
- h.State["tlsCertTags"] = tlsCertTags
112
+ // file certificate loader
113
+ firstLine := h.RemainingArgs()
114
+ switch len(firstLine) {
115
+ case 0:
116
+ case 1:
117
+ if firstLine[0] == "internal" {
118
+ internalIssuer = new(caddytls.InternalIssuer)
119
+ } else if !strings.Contains(firstLine[0], "@") {
120
+ return nil, h.Err("single argument must either be 'internal' or an email address")
121
+ } else {
122
+ if acmeIssuer == nil {
123
+ acmeIssuer = new(caddytls.ACMEIssuer)
124
}
125
+ acmeIssuer.Email = firstLine[0]
126
+ }
127
160
- tag, ok := tlsCertTags[certFilename]
161
- if !ok {
162
- // haven't seen this cert file yet, let's give it a tag
163
- // and add a loader for it
164
- tag = fmt.Sprintf("cert%d", len(tlsCertTags))
165
- fileLoader = append(fileLoader, caddytls.CertKeyFilePair{
166
- Certificate: certFilename,
167
- Key: keyFilename,
168
- Tags: []string{tag},
169
- })
170
- // remember this for next time we see this cert file
171
- tlsCertTags[certFilename] = tag
172
- }
173
- certSelector.AnyTag = append(certSelector.AnyTag, tag)
128
+ case 2:
129
+ certFilename := firstLine[0]
130
+ keyFilename := firstLine[1]
131
+
132
+ // tag this certificate so if multiple certs match, specifically
133
+ // this one that the user has provided will be used, see #2588:
134
+ // https://github.com/caddyserver/caddy/issues/2588 ... but we
135
+ // must be careful about how we do this; being careless will
136
+ // lead to failed handshakes
137
+ //
138
+ // we need to remember which cert files we've seen, since we
139
+ // must load each cert only once; otherwise, they each get a
140
+ // different tag... since a cert loaded twice has the same
141
+ // bytes, it will overwrite the first one in the cache, and
142
+ // only the last cert (and its tag) will survive, so any conn
143
+ // policy that is looking for any tag other than the last one
144
+ // to be loaded won't find it, and TLS handshakes will fail
145
+ // (see end of issue #3004)
146
+ //
147
+ // tlsCertTags maps certificate filenames to their tag.
148
+ // This is used to remember which tag is used for each
149
+ // certificate files, since we need to avoid loading
150
+ // the same certificate files more than once, overwriting
151
+ // previous tags
152
+ tlsCertTags, ok := h.State["tlsCertTags"].(map[string]string)
153
+ if !ok {
154
+ tlsCertTags = make(map[string]string)
155
+ h.State["tlsCertTags"] = tlsCertTags
156
+ }
157
175
- default:
176
- return nil, h.ArgErr()
158
+ tag, ok := tlsCertTags[certFilename]
159
+ if !ok {
160
+ // haven't seen this cert file yet, let's give it a tag
161
+ // and add a loader for it
162
+ tag = fmt.Sprintf("cert%d", len(tlsCertTags))
163
+ fileLoader = append(fileLoader, caddytls.CertKeyFilePair{
164
+ Certificate: certFilename,
165
+ Key: keyFilename,
166
+ Tags: []string{tag},
167
+ })
168
+ // remember this for next time we see this cert file
169
+ tlsCertTags[certFilename] = tag
170
}
171
+ certSelector.AnyTag = append(certSelector.AnyTag, tag)
172
179
- var hasBlock bool
180
- for nesting := h.Nesting(); h.NextBlock(nesting); {
181
- hasBlock = true
173
+ default:
174
+ return nil, h.ArgErr()
175
+ }
176
+
177
+ var hasBlock bool
178
+ for h.NextBlock(0) {
179
+ hasBlock = true
180
183
- switch h.Val() {
184
- case "protocols":
185
- args := h.RemainingArgs()
186
- if len(args) == 0 {
187
- return nil, h.Errf("protocols requires one or two arguments")
181
+ switch h.Val() {
182
+ case "protocols":
183
+ args := h.RemainingArgs()
184
+ if len(args) == 0 {
185
+ return nil, h.Errf("protocols requires one or two arguments")
186
+ }
187
+ if len(args) > 0 {
188
+ if _, ok := caddytls.SupportedProtocols[args[0]]; !ok {
189
+ return nil, h.Errf("wrong protocol name or protocol not supported: '%s'", args[0])
190
}
189
- if len(args) > 0 {
190
- if _, ok := caddytls.SupportedProtocols[args[0]]; !ok {
191
- return nil, h.Errf("wrong protocol name or protocol not supported: '%s'", args[0])
192
- }
193
- cp.ProtocolMin = args[0]
191
+ cp.ProtocolMin = args[0]
192
+ }
193
+ if len(args) > 1 {
194
+ if _, ok := caddytls.SupportedProtocols[args[1]]; !ok {
195
+ return nil, h.Errf("wrong protocol name or protocol not supported: '%s'", args[1])
196
}
195
- if len(args) > 1 {
196
- if _, ok := caddytls.SupportedProtocols[args[1]]; !ok {
197
- return nil, h.Errf("wrong protocol name or protocol not supported: '%s'", args[1])
198
- }
199
- cp.ProtocolMax = args[1]
197
+ cp.ProtocolMax = args[1]
198
+ }
199
+
200
+ case "ciphers":
201
+ for h.NextArg() {
202
+ if !caddytls.CipherSuiteNameSupported(h.Val()) {
203
+ return nil, h.Errf("wrong cipher suite name or cipher suite not supported: '%s'", h.Val())
204
}
205
+ cp.CipherSuites = append(cp.CipherSuites, h.Val())
206
+ }
207
202
- case "ciphers":
203
- for h.NextArg() {
204
- if !caddytls.CipherSuiteNameSupported(h.Val()) {
205
- return nil, h.Errf("wrong cipher suite name or cipher suite not supported: '%s'", h.Val())
206
- }
207
- cp.CipherSuites = append(cp.CipherSuites, h.Val())
208
+ case "curves":
209
+ for h.NextArg() {
210
+ if _, ok := caddytls.SupportedCurves[h.Val()]; !ok {
211
+ return nil, h.Errf("Wrong curve name or curve not supported: '%s'", h.Val())
212
}
213
+ cp.Curves = append(cp.Curves, h.Val())
214
+ }
215
210
- case "curves":
211
- for h.NextArg() {
212
- if _, ok := caddytls.SupportedCurves[h.Val()]; !ok {
213
- return nil, h.Errf("Wrong curve name or curve not supported: '%s'", h.Val())
216
+ case "client_auth":
217
+ cp.ClientAuthentication = &caddytls.ClientAuthentication{}
218
+ for nesting := h.Nesting(); h.NextBlock(nesting); {
219
+ subdir := h.Val()
220
+ switch subdir {
221
+ case "verifier":
222
+ if !h.NextArg() {
223
+ return nil, h.ArgErr()
224
}
215
- cp.Curves = append(cp.Curves, h.Val())
216
- }
225
218
- case "client_auth":
219
- cp.ClientAuthentication = &caddytls.ClientAuthentication{}
220
- for nesting := h.Nesting(); h.NextBlock(nesting); {
221
- subdir := h.Val()
222
- switch subdir {
223
- case "verifier":
224
- if !h.NextArg() {
225
- return nil, h.ArgErr()
226
- }
226
+ vType := h.Val()
227
+ modID := "tls.client_auth." + vType
228
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
229
+ if err != nil {
230
+ return nil, err
231
+ }
232
228
- vType := h.Val()
229
- modID := "tls.client_auth." + vType
230
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
231
- if err != nil {
232
- return nil, err
233
- }
233
+ _, ok := unm.(caddytls.ClientCertificateVerifier)
234
+ if !ok {
235
+ return nil, h.Dispenser.Errf("module %s is not a caddytls.ClientCertificatVerifier", modID)
236
+ }
237
235
- _, ok := unm.(caddytls.ClientCertificateVerifier)
236
- if !ok {
237
- return nil, h.Dispenser.Errf("module %s is not a caddytls.ClientCertificatVerifier", modID)
238
- }
238
+ cp.ClientAuthentication.VerifiersRaw = append(cp.ClientAuthentication.VerifiersRaw, caddyconfig.JSONModuleObject(unm, "verifier", vType, h.warnings))
239
+ case "mode":
240
+ if !h.Args(&cp.ClientAuthentication.Mode) {
241
+ return nil, h.ArgErr()
242
+ }
243
+ if h.NextArg() {
244
+ return nil, h.ArgErr()
245
+ }
246
240
- cp.ClientAuthentication.VerifiersRaw = append(cp.ClientAuthentication.VerifiersRaw, caddyconfig.JSONModuleObject(unm, "verifier", vType, h.warnings))
241
- case "mode":
242
- if !h.Args(&cp.ClientAuthentication.Mode) {
243
- return nil, h.ArgErr()
244
- }
245
- if h.NextArg() {
246
- return nil, h.ArgErr()
247
- }
247
+ case "trusted_ca_cert",
248
+ "trusted_leaf_cert":
249
+ if !h.NextArg() {
250
+ return nil, h.ArgErr()
251
+ }
252
+ if subdir == "trusted_ca_cert" {
253
+ cp.ClientAuthentication.TrustedCACerts = append(cp.ClientAuthentication.TrustedCACerts, h.Val())
254
+ } else {
255
+ cp.ClientAuthentication.TrustedLeafCerts = append(cp.ClientAuthentication.TrustedLeafCerts, h.Val())
256
+ }
257
249
- case "trusted_ca_cert",
250
- "trusted_leaf_cert":
251
- if !h.NextArg() {
252
- return nil, h.ArgErr()
258
+ case "trusted_ca_cert_file",
259
+ "trusted_leaf_cert_file":
260
+ if !h.NextArg() {
261
+ return nil, h.ArgErr()
262
+ }
263
+ filename := h.Val()
264
+ certDataPEM, err := os.ReadFile(filename)
265
+ if err != nil {
266
+ return nil, err
267
+ }
268
+ // while block is not nil, we have more certificates in the file
269
+ for block, rest := pem.Decode(certDataPEM); block != nil; block, rest = pem.Decode(rest) {
270
+ if block.Type != "CERTIFICATE" {
271
+ return nil, h.Errf("no CERTIFICATE pem block found in %s", filename)
272
}
254
- if subdir == "trusted_ca_cert" {
255
- cp.ClientAuthentication.TrustedCACerts = append(cp.ClientAuthentication.TrustedCACerts, h.Val())
273
+ if subdir == "trusted_ca_cert_file" {
274
+ cp.ClientAuthentication.TrustedCACerts = append(
275
+ cp.ClientAuthentication.TrustedCACerts,
276
+ base64.StdEncoding.EncodeToString(block.Bytes),
277
+ )
278
} else {
257
- cp.ClientAuthentication.TrustedLeafCerts = append(cp.ClientAuthentication.TrustedLeafCerts, h.Val())
258
- }
259
-
260
- case "trusted_ca_cert_file",
261
- "trusted_leaf_cert_file":
262
- if !h.NextArg() {
263
- return nil, h.ArgErr()
264
- }
265
- filename := h.Val()
266
- certDataPEM, err := os.ReadFile(filename)
267
- if err != nil {
268
- return nil, err
279
+ cp.ClientAuthentication.TrustedLeafCerts = append(
280
+ cp.ClientAuthentication.TrustedLeafCerts,
281
+ base64.StdEncoding.EncodeToString(block.Bytes),
282
+ )
283
}
270
- // while block is not nil, we have more certificates in the file
271
- for block, rest := pem.Decode(certDataPEM); block != nil; block, rest = pem.Decode(rest) {
272
- if block.Type != "CERTIFICATE" {
273
- return nil, h.Errf("no CERTIFICATE pem block found in %s", filename)
274
- }
275
- if subdir == "trusted_ca_cert_file" {
276
- cp.ClientAuthentication.TrustedCACerts = append(
277
- cp.ClientAuthentication.TrustedCACerts,
278
- base64.StdEncoding.EncodeToString(block.Bytes),
279
- )
280
- } else {
281
- cp.ClientAuthentication.TrustedLeafCerts = append(
282
- cp.ClientAuthentication.TrustedLeafCerts,
283
- base64.StdEncoding.EncodeToString(block.Bytes),
284
- )
285
- }
286
- }
287
- // if we decoded nothing, return an error
288
- if len(cp.ClientAuthentication.TrustedCACerts) == 0 && len(cp.ClientAuthentication.TrustedLeafCerts) == 0 {
289
- return nil, h.Errf("no CERTIFICATE pem block found in %s", filename)
290
- }
291
-
292
- default:
293
- return nil, h.Errf("unknown subdirective for client_auth: %s", subdir)
284
}
295
- }
285
+ // if we decoded nothing, return an error
286
+ if len(cp.ClientAuthentication.TrustedCACerts) == 0 && len(cp.ClientAuthentication.TrustedLeafCerts) == 0 {
287
+ return nil, h.Errf("no CERTIFICATE pem block found in %s", filename)
288
+ }
289
297
- case "alpn":
298
- args := h.RemainingArgs()
299
- if len(args) == 0 {
300
- return nil, h.ArgErr()
290
+ default:
291
+ return nil, h.Errf("unknown subdirective for client_auth: %s", subdir)
292
}
302
- cp.ALPN = args
293
+ }
294
304
- case "load":
305
- folderLoader = append(folderLoader, h.RemainingArgs()...)
295
+ case "alpn":
296
+ args := h.RemainingArgs()
297
+ if len(args) == 0 {
298
+ return nil, h.ArgErr()
299
+ }
300
+ cp.ALPN = args
301
307
- case "ca":
308
- arg := h.RemainingArgs()
309
- if len(arg) != 1 {
310
- return nil, h.ArgErr()
311
- }
312
- if acmeIssuer == nil {
313
- acmeIssuer = new(caddytls.ACMEIssuer)
314
- }
315
- acmeIssuer.CA = arg[0]
302
+ case "load":
303
+ folderLoader = append(folderLoader, h.RemainingArgs()...)
304
317
- case "key_type":
318
- arg := h.RemainingArgs()
319
- if len(arg) != 1 {
320
- return nil, h.ArgErr()
321
- }
322
- keyType = arg[0]
305
+ case "ca":
306
+ arg := h.RemainingArgs()
307
+ if len(arg) != 1 {
308
+ return nil, h.ArgErr()
309
+ }
310
+ if acmeIssuer == nil {
311
+ acmeIssuer = new(caddytls.ACMEIssuer)
312
+ }
313
+ acmeIssuer.CA = arg[0]
314
324
- case "eab":
325
- arg := h.RemainingArgs()
326
- if len(arg) != 2 {
327
- return nil, h.ArgErr()
328
- }
329
- if acmeIssuer == nil {
330
- acmeIssuer = new(caddytls.ACMEIssuer)
331
- }
332
- acmeIssuer.ExternalAccount = &acme.EAB{
333
- KeyID: arg[0],
334
- MACKey: arg[1],
335
- }
315
+ case "key_type":
316
+ arg := h.RemainingArgs()
317
+ if len(arg) != 1 {
318
+ return nil, h.ArgErr()
319
+ }
320
+ keyType = arg[0]
321
337
- case "issuer":
338
- if !h.NextArg() {
339
- return nil, h.ArgErr()
340
- }
341
- modName := h.Val()
342
- modID := "tls.issuance." + modName
343
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
344
- if err != nil {
345
- return nil, err
346
- }
347
- issuer, ok := unm.(certmagic.Issuer)
348
- if !ok {
349
- return nil, h.Errf("module %s (%T) is not a certmagic.Issuer", modID, unm)
350
- }
351
- issuers = append(issuers, issuer)
322
+ case "eab":
323
+ arg := h.RemainingArgs()
324
+ if len(arg) != 2 {
325
+ return nil, h.ArgErr()
326
+ }
327
+ if acmeIssuer == nil {
328
+ acmeIssuer = new(caddytls.ACMEIssuer)
329
+ }
330
+ acmeIssuer.ExternalAccount = &acme.EAB{
331
+ KeyID: arg[0],
332
+ MACKey: arg[1],
333
+ }
334
353
- case "get_certificate":
354
- if !h.NextArg() {
355
- return nil, h.ArgErr()
356
- }
357
- modName := h.Val()
358
- modID := "tls.get_certificate." + modName
359
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
360
- if err != nil {
361
- return nil, err
362
- }
363
- certManager, ok := unm.(certmagic.Manager)
364
- if !ok {
365
- return nil, h.Errf("module %s (%T) is not a certmagic.CertificateManager", modID, unm)
366
- }
367
- certManagers = append(certManagers, certManager)
335
+ case "issuer":
336
+ if !h.NextArg() {
337
+ return nil, h.ArgErr()
338
+ }
339
+ modName := h.Val()
340
+ modID := "tls.issuance." + modName
341
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
342
+ if err != nil {
343
+ return nil, err
344
+ }
345
+ issuer, ok := unm.(certmagic.Issuer)
346
+ if !ok {
347
+ return nil, h.Errf("module %s (%T) is not a certmagic.Issuer", modID, unm)
348
+ }
349
+ issuers = append(issuers, issuer)
350
369
- case "dns":
370
- if !h.NextArg() {
371
- return nil, h.ArgErr()
372
- }
373
- provName := h.Val()
374
- if acmeIssuer == nil {
375
- acmeIssuer = new(caddytls.ACMEIssuer)
376
- }
377
- if acmeIssuer.Challenges == nil {
378
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
379
- }
380
- if acmeIssuer.Challenges.DNS == nil {
381
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
382
- }
383
- modID := "dns.providers." + provName
384
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
385
- if err != nil {
386
- return nil, err
387
- }
388
- acmeIssuer.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, h.warnings)
351
+ case "get_certificate":
352
+ if !h.NextArg() {
353
+ return nil, h.ArgErr()
354
+ }
355
+ modName := h.Val()
356
+ modID := "tls.get_certificate." + modName
357
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
358
+ if err != nil {
359
+ return nil, err
360
+ }
361
+ certManager, ok := unm.(certmagic.Manager)
362
+ if !ok {
363
+ return nil, h.Errf("module %s (%T) is not a certmagic.CertificateManager", modID, unm)
364
+ }
365
+ certManagers = append(certManagers, certManager)
366
390
- case "resolvers":
391
- args := h.RemainingArgs()
392
- if len(args) == 0 {
393
- return nil, h.ArgErr()
394
- }
395
- if acmeIssuer == nil {
396
- acmeIssuer = new(caddytls.ACMEIssuer)
397
- }
398
- if acmeIssuer.Challenges == nil {
399
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
400
- }
401
- if acmeIssuer.Challenges.DNS == nil {
402
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
403
- }
404
- acmeIssuer.Challenges.DNS.Resolvers = args
367
+ case "dns":
368
+ if !h.NextArg() {
369
+ return nil, h.ArgErr()
370
+ }
371
+ provName := h.Val()
372
+ if acmeIssuer == nil {
373
+ acmeIssuer = new(caddytls.ACMEIssuer)
374
+ }
375
+ if acmeIssuer.Challenges == nil {
376
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
377
+ }
378
+ if acmeIssuer.Challenges.DNS == nil {
379
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
380
+ }
381
+ modID := "dns.providers." + provName
382
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
383
+ if err != nil {
384
+ return nil, err
385
+ }
386
+ acmeIssuer.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, h.warnings)
387
406
- case "propagation_delay":
407
- arg := h.RemainingArgs()
408
- if len(arg) != 1 {
409
- return nil, h.ArgErr()
410
- }
411
- delayStr := arg[0]
412
- delay, err := caddy.ParseDuration(delayStr)
413
- if err != nil {
414
- return nil, h.Errf("invalid propagation_delay duration %s: %v", delayStr, err)
415
- }
416
- if acmeIssuer == nil {
417
- acmeIssuer = new(caddytls.ACMEIssuer)
418
- }
419
- if acmeIssuer.Challenges == nil {
420
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
421
- }
422
- if acmeIssuer.Challenges.DNS == nil {
423
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
424
- }
425
- acmeIssuer.Challenges.DNS.PropagationDelay = caddy.Duration(delay)
388
+ case "resolvers":
389
+ args := h.RemainingArgs()
390
+ if len(args) == 0 {
391
+ return nil, h.ArgErr()
392
+ }
393
+ if acmeIssuer == nil {
394
+ acmeIssuer = new(caddytls.ACMEIssuer)
395
+ }
396
+ if acmeIssuer.Challenges == nil {
397
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
398
+ }
399
+ if acmeIssuer.Challenges.DNS == nil {
400
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
401
+ }
402
+ acmeIssuer.Challenges.DNS.Resolvers = args
403
427
- case "propagation_timeout":
428
- arg := h.RemainingArgs()
429
- if len(arg) != 1 {
430
- return nil, h.ArgErr()
431
- }
432
- timeoutStr := arg[0]
433
- var timeout time.Duration
434
- if timeoutStr == "-1" {
435
- timeout = time.Duration(-1)
436
- } else {
437
- var err error
438
- timeout, err = caddy.ParseDuration(timeoutStr)
439
- if err != nil {
440
- return nil, h.Errf("invalid propagation_timeout duration %s: %v", timeoutStr, err)
441
- }
442
- }
443
- if acmeIssuer == nil {
444
- acmeIssuer = new(caddytls.ACMEIssuer)
445
- }
446
- if acmeIssuer.Challenges == nil {
447
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
448
- }
449
- if acmeIssuer.Challenges.DNS == nil {
450
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
451
- }
452
- acmeIssuer.Challenges.DNS.PropagationTimeout = caddy.Duration(timeout)
404
+ case "propagation_delay":
405
+ arg := h.RemainingArgs()
406
+ if len(arg) != 1 {
407
+ return nil, h.ArgErr()
408
+ }
409
+ delayStr := arg[0]
410
+ delay, err := caddy.ParseDuration(delayStr)
411
+ if err != nil {
412
+ return nil, h.Errf("invalid propagation_delay duration %s: %v", delayStr, err)
413
+ }
414
+ if acmeIssuer == nil {
415
+ acmeIssuer = new(caddytls.ACMEIssuer)
416
+ }
417
+ if acmeIssuer.Challenges == nil {
418
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
419
+ }
420
+ if acmeIssuer.Challenges.DNS == nil {
421
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
422
+ }
423
+ acmeIssuer.Challenges.DNS.PropagationDelay = caddy.Duration(delay)
424
454
- case "dns_ttl":
455
- arg := h.RemainingArgs()
456
- if len(arg) != 1 {
457
- return nil, h.ArgErr()
458
- }
459
- ttlStr := arg[0]
460
- ttl, err := caddy.ParseDuration(ttlStr)
425
+ case "propagation_timeout":
426
+ arg := h.RemainingArgs()
427
+ if len(arg) != 1 {
428
+ return nil, h.ArgErr()
429
+ }
430
+ timeoutStr := arg[0]
431
+ var timeout time.Duration
432
+ if timeoutStr == "-1" {
433
+ timeout = time.Duration(-1)
434
+ } else {
435
+ var err error
436
+ timeout, err = caddy.ParseDuration(timeoutStr)
437
if err != nil {
462
- return nil, h.Errf("invalid dns_ttl duration %s: %v", ttlStr, err)
463
- }
464
- if acmeIssuer == nil {
465
- acmeIssuer = new(caddytls.ACMEIssuer)
466
- }
467
- if acmeIssuer.Challenges == nil {
468
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
438
+ return nil, h.Errf("invalid propagation_timeout duration %s: %v", timeoutStr, err)
439
}
470
- if acmeIssuer.Challenges.DNS == nil {
471
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
472
- }
473
- acmeIssuer.Challenges.DNS.TTL = caddy.Duration(ttl)
440
+ }
441
+ if acmeIssuer == nil {
442
+ acmeIssuer = new(caddytls.ACMEIssuer)
443
+ }
444
+ if acmeIssuer.Challenges == nil {
445
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
446
+ }
447
+ if acmeIssuer.Challenges.DNS == nil {
448
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
449
+ }
450
+ acmeIssuer.Challenges.DNS.PropagationTimeout = caddy.Duration(timeout)
451
475
- case "dns_challenge_override_domain":
476
- arg := h.RemainingArgs()
477
- if len(arg) != 1 {
478
- return nil, h.ArgErr()
479
- }
480
- if acmeIssuer == nil {
481
- acmeIssuer = new(caddytls.ACMEIssuer)
482
- }
483
- if acmeIssuer.Challenges == nil {
484
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
485
- }
486
- if acmeIssuer.Challenges.DNS == nil {
487
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
488
- }
489
- acmeIssuer.Challenges.DNS.OverrideDomain = arg[0]
452
+ case "dns_ttl":
453
+ arg := h.RemainingArgs()
454
+ if len(arg) != 1 {
455
+ return nil, h.ArgErr()
456
+ }
457
+ ttlStr := arg[0]
458
+ ttl, err := caddy.ParseDuration(ttlStr)
459
+ if err != nil {
460
+ return nil, h.Errf("invalid dns_ttl duration %s: %v", ttlStr, err)
461
+ }
462
+ if acmeIssuer == nil {
463
+ acmeIssuer = new(caddytls.ACMEIssuer)
464
+ }
465
+ if acmeIssuer.Challenges == nil {
466
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
467
+ }
468
+ if acmeIssuer.Challenges.DNS == nil {
469
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
470
+ }
471
+ acmeIssuer.Challenges.DNS.TTL = caddy.Duration(ttl)
472
491
- case "ca_root":
492
- arg := h.RemainingArgs()
493
- if len(arg) != 1 {
494
- return nil, h.ArgErr()
495
- }
496
- if acmeIssuer == nil {
497
- acmeIssuer = new(caddytls.ACMEIssuer)
498
- }
499
- acmeIssuer.TrustedRootsPEMFiles = append(acmeIssuer.TrustedRootsPEMFiles, arg[0])
473
+ case "dns_challenge_override_domain":
474
+ arg := h.RemainingArgs()
475
+ if len(arg) != 1 {
476
+ return nil, h.ArgErr()
477
+ }
478
+ if acmeIssuer == nil {
479
+ acmeIssuer = new(caddytls.ACMEIssuer)
480
+ }
481
+ if acmeIssuer.Challenges == nil {
482
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
483
+ }
484
+ if acmeIssuer.Challenges.DNS == nil {
485
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
486
+ }
487
+ acmeIssuer.Challenges.DNS.OverrideDomain = arg[0]
488
501
- case "on_demand":
502
- if h.NextArg() {
503
- return nil, h.ArgErr()
504
- }
505
- onDemand = true
489
+ case "ca_root":
490
+ arg := h.RemainingArgs()
491
+ if len(arg) != 1 {
492
+ return nil, h.ArgErr()
493
+ }
494
+ if acmeIssuer == nil {
495
+ acmeIssuer = new(caddytls.ACMEIssuer)
496
+ }
497
+ acmeIssuer.TrustedRootsPEMFiles = append(acmeIssuer.TrustedRootsPEMFiles, arg[0])
498
507
- case "reuse_private_keys":
508
- if h.NextArg() {
509
- return nil, h.ArgErr()
510
- }
511
- reusePrivateKeys = true
499
+ case "on_demand":
500
+ if h.NextArg() {
501
+ return nil, h.ArgErr()
502
+ }
503
+ onDemand = true
504
513
- case "insecure_secrets_log":
514
- if !h.NextArg() {
515
- return nil, h.ArgErr()
516
- }
517
- cp.InsecureSecretsLog = h.Val()
505
+ case "reuse_private_keys":
506
+ if h.NextArg() {
507
+ return nil, h.ArgErr()
508
+ }
509
+ reusePrivateKeys = true
510
519
- default:
520
- return nil, h.Errf("unknown subdirective: %s", h.Val())
511
+ case "insecure_secrets_log":
512
+ if !h.NextArg() {
513
+ return nil, h.ArgErr()
514
}
522
- }
515
+ cp.InsecureSecretsLog = h.Val()
516
524
- // a naked tls directive is not allowed
525
- if len(firstLine) == 0 && !hasBlock {
526
- return nil, h.ArgErr()
517
+ default:
518
+ return nil, h.Errf("unknown subdirective: %s", h.Val())
519
}
520
}
521
522
+ // a naked tls directive is not allowed
523
+ if len(firstLine) == 0 && !hasBlock {
524
+ return nil, h.ArgErr()
525
+ }
526
+
527
// begin building the final config values
528
configVals := []ConfigValue{}
529
@@ -646,10 +643,7 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
643
//
644
// root [<matcher>] <path>
645
func parseRoot(h Helper) ([]ConfigValue, error) {
649
- // consume directive name
650
- if !h.NextArg() {
651
- return nil, h.ArgErr()
652
- }
646
+ h.Next() // consume directive name
647
648
// count the tokens to determine what to do
649
argsCount := h.CountRemainingArgs()
@@ -673,11 +667,8 @@ func parseRoot(h Helper) ([]ConfigValue, error) {
667
if err != nil {
668
return nil, err
669
}
670
+ h.Next() // consume directive name again, matcher parsing does a reset
671
677
- // consume directive name, again, because extracting matcher does a reset
678
- if !h.NextArg() {
679
- return nil, h.ArgErr()
680
- }
672
// advance to the root path
673
if !h.NextArg() {
674
return nil, h.ArgErr()
@@ -690,17 +681,14 @@ func parseRoot(h Helper) ([]ConfigValue, error) {
681
//
682
// fs <filesystem>
683
func parseFilesystem(h Helper) (caddyhttp.MiddlewareHandler, error) {
693
- var name string
694
- for h.Next() {
695
- if !h.NextArg() {
696
- return nil, h.ArgErr()
697
- }
698
- name = h.Val()
699
- if h.NextArg() {
700
- return nil, h.ArgErr()
701
- }
684
+ h.Next() // consume directive name
685
+ if !h.NextArg() {
686
+ return nil, h.ArgErr()
687
}
703
- return caddyhttp.VarsMiddleware{"fs": name}, nil
688
+ if h.NextArg() {
689
+ return nil, h.ArgErr()
690
+ }
691
+ return caddyhttp.VarsMiddleware{"fs": h.Val()}, nil
692
}
693
694
// parseVars parses the vars directive. See its UnmarshalCaddyfile method for syntax.
@@ -720,10 +708,7 @@ func parseVars(h Helper) (caddyhttp.MiddlewareHandler, error) {
708
// respond with HTTP 200 and no Location header; redirect is performed
709
// with JS and a meta tag).
710
func parseRedir(h Helper) (caddyhttp.MiddlewareHandler, error) {
723
- if !h.Next() {
724
- return nil, h.ArgErr()
725
- }
726
-
711
+ h.Next() // consume directive name
712
if !h.NextArg() {
713
return nil, h.ArgErr()
714
}
@@ -739,8 +724,10 @@ func parseRedir(h Helper) (caddyhttp.MiddlewareHandler, error) {
724
switch code {
725
case "permanent":
726
code = "301"
727
+
728
case "temporary", "":
729
code = "302"
730
+
731
case "html":
732
// Script tag comes first since that will better imitate a redirect in the browser's
733
// history, but the meta tag is a fallback for most non-JS clients.
@@ -758,6 +745,7 @@ func parseRedir(h Helper) (caddyhttp.MiddlewareHandler, error) {
745
body = fmt.Sprintf(metaRedir, safeTo, safeTo, safeTo, safeTo)
746
hdr = http.Header{"Content-Type": []string{"text/html; charset=utf-8"}}
747
code = "200" // don't redirect non-browser clients
748
+
749
default:
750
// Allow placeholders for the code
751
if strings.HasPrefix(code, "{") {
@@ -796,10 +784,7 @@ func parseRedir(h Helper) (caddyhttp.MiddlewareHandler, error) {
784
func parseRespond(h Helper) (caddyhttp.MiddlewareHandler, error) {
785
sr := new(caddyhttp.StaticResponse)
786
err := sr.UnmarshalCaddyfile(h.Dispenser)
799
- if err != nil {
800
- return nil, err
801
- }
802
- return sr, nil
787
+ return sr, err
788
}
789
790
// parseAbort parses the abort directive.
@@ -815,10 +800,7 @@ func parseAbort(h Helper) (caddyhttp.MiddlewareHandler, error) {
800
func parseError(h Helper) (caddyhttp.MiddlewareHandler, error) {
801
se := new(caddyhttp.StaticError)
802
err := se.UnmarshalCaddyfile(h.Dispenser)
818
- if err != nil {
819
- return nil, err
820
- }
821
- return se, nil
803
+ return se, err
804
}
805
806
// parseRoute parses the route directive.
@@ -844,11 +826,11 @@ func parseHandle(h Helper) (caddyhttp.MiddlewareHandler, error) {
826
}
827
828
func parseHandleErrors(h Helper) ([]ConfigValue, error) {
847
- h.Next()
848
- args := h.RemainingArgs()
829
+ h.Next() // consume directive name
830
+
831
expression := ""
832
+ args := h.RemainingArgs()
833
if len(args) > 0 {
851
- expression = ""
834
codes := []string{}
835
for _, val := range args {
836
if len(val) != 3 {
@@ -951,184 +933,185 @@ func parseLog(h Helper) ([]ConfigValue, error) {
933
// level. The parseAsGlobalOption parameter is used to distinguish any differing logic
934
// between the two.
935
func parseLogHelper(h Helper, globalLogNames map[string]struct{}) ([]ConfigValue, error) {
936
+ h.Next() // consume option name
937
+
938
// When the globalLogNames parameter is passed in, we make
939
// modifications to the parsing behavior.
940
parseAsGlobalOption := globalLogNames != nil
941
942
var configValues []ConfigValue
959
- for h.Next() {
960
- // Logic below expects that a name is always present when a
961
- // global option is being parsed; or an optional override
962
- // is supported for access logs.
963
- var logName string
943
965
- if parseAsGlobalOption {
966
- if h.NextArg() {
967
- logName = h.Val()
944
+ // Logic below expects that a name is always present when a
945
+ // global option is being parsed; or an optional override
946
+ // is supported for access logs.
947
+ var logName string
948
969
- // Only a single argument is supported.
970
- if h.NextArg() {
971
- return nil, h.ArgErr()
972
- }
973
- } else {
974
- // If there is no log name specified, we
975
- // reference the default logger. See the
976
- // setupNewDefault function in the logging
977
- // package for where this is configured.
978
- logName = caddy.DefaultLoggerName
979
- }
949
+ if parseAsGlobalOption {
950
+ if h.NextArg() {
951
+ logName = h.Val()
952
981
- // Verify this name is unused.
982
- _, used := globalLogNames[logName]
983
- if used {
984
- return nil, h.Err("duplicate global log option for: " + logName)
953
+ // Only a single argument is supported.
954
+ if h.NextArg() {
955
+ return nil, h.ArgErr()
956
}
986
- globalLogNames[logName] = struct{}{}
957
} else {
988
- // An optional override of the logger name can be provided;
989
- // otherwise a default will be used, like "log0", "log1", etc.
990
- if h.NextArg() {
991
- logName = h.Val()
958
+ // If there is no log name specified, we
959
+ // reference the default logger. See the
960
+ // setupNewDefault function in the logging
961
+ // package for where this is configured.
962
+ logName = caddy.DefaultLoggerName
963
+ }
964
993
- // Only a single argument is supported.
994
- if h.NextArg() {
995
- return nil, h.ArgErr()
996
- }
997
- }
965
+ // Verify this name is unused.
966
+ _, used := globalLogNames[logName]
967
+ if used {
968
+ return nil, h.Err("duplicate global log option for: " + logName)
969
}
970
+ globalLogNames[logName] = struct{}{}
971
+ } else {
972
+ // An optional override of the logger name can be provided;
973
+ // otherwise a default will be used, like "log0", "log1", etc.
974
+ if h.NextArg() {
975
+ logName = h.Val()
976
1000
- cl := new(caddy.CustomLog)
977
+ // Only a single argument is supported.
978
+ if h.NextArg() {
979
+ return nil, h.ArgErr()
980
+ }
981
+ }
982
+ }
983
1002
- // allow overriding the current site block's hostnames for this logger;
1003
- // this is useful for setting up loggers per subdomain in a site block
1004
- // with a wildcard domain
1005
- customHostnames := []string{}
984
+ cl := new(caddy.CustomLog)
985
1007
- for h.NextBlock(0) {
1008
- switch h.Val() {
1009
- case "hostnames":
1010
- if parseAsGlobalOption {
1011
- return nil, h.Err("hostnames is not allowed in the log global options")
1012
- }
1013
- args := h.RemainingArgs()
1014
- if len(args) == 0 {
1015
- return nil, h.ArgErr()
1016
- }
1017
- customHostnames = append(customHostnames, args...)
986
+ // allow overriding the current site block's hostnames for this logger;
987
+ // this is useful for setting up loggers per subdomain in a site block
988
+ // with a wildcard domain
989
+ customHostnames := []string{}
990
1019
- case "output":
1020
- if !h.NextArg() {
1021
- return nil, h.ArgErr()
1022
- }
1023
- moduleName := h.Val()
1024
-
1025
- // can't use the usual caddyfile.Unmarshaler flow with the
1026
- // standard writers because they are in the caddy package
1027
- // (because they are the default) and implementing that
1028
- // interface there would unfortunately create circular import
1029
- var wo caddy.WriterOpener
1030
- switch moduleName {
1031
- case "stdout":
1032
- wo = caddy.StdoutWriter{}
1033
- case "stderr":
1034
- wo = caddy.StderrWriter{}
1035
- case "discard":
1036
- wo = caddy.DiscardWriter{}
1037
- default:
1038
- modID := "caddy.logging.writers." + moduleName
1039
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
1040
- if err != nil {
1041
- return nil, err
1042
- }
1043
- var ok bool
1044
- wo, ok = unm.(caddy.WriterOpener)
1045
- if !ok {
1046
- return nil, h.Errf("module %s (%T) is not a WriterOpener", modID, unm)
1047
- }
1048
- }
1049
- cl.WriterRaw = caddyconfig.JSONModuleObject(wo, "output", moduleName, h.warnings)
991
+ for h.NextBlock(0) {
992
+ switch h.Val() {
993
+ case "hostnames":
994
+ if parseAsGlobalOption {
995
+ return nil, h.Err("hostnames is not allowed in the log global options")
996
+ }
997
+ args := h.RemainingArgs()
998
+ if len(args) == 0 {
999
+ return nil, h.ArgErr()
1000
+ }
1001
+ customHostnames = append(customHostnames, args...)
1002
1051
- case "format":
1052
- if !h.NextArg() {
1053
- return nil, h.ArgErr()
1054
- }
1055
- moduleName := h.Val()
1056
- moduleID := "caddy.logging.encoders." + moduleName
1057
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, moduleID)
1003
+ case "output":
1004
+ if !h.NextArg() {
1005
+ return nil, h.ArgErr()
1006
+ }
1007
+ moduleName := h.Val()
1008
+
1009
+ // can't use the usual caddyfile.Unmarshaler flow with the
1010
+ // standard writers because they are in the caddy package
1011
+ // (because they are the default) and implementing that
1012
+ // interface there would unfortunately create circular import
1013
+ var wo caddy.WriterOpener
1014
+ switch moduleName {
1015
+ case "stdout":
1016
+ wo = caddy.StdoutWriter{}
1017
+ case "stderr":
1018
+ wo = caddy.StderrWriter{}
1019
+ case "discard":
1020
+ wo = caddy.DiscardWriter{}
1021
+ default:
1022
+ modID := "caddy.logging.writers." + moduleName
1023
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
1024
if err != nil {
1025
return nil, err
1026
}
1061
- enc, ok := unm.(zapcore.Encoder)
1027
+ var ok bool
1028
+ wo, ok = unm.(caddy.WriterOpener)
1029
if !ok {
1063
- return nil, h.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
1030
+ return nil, h.Errf("module %s (%T) is not a WriterOpener", modID, unm)
1031
}
1065
- cl.EncoderRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, h.warnings)
1032
+ }
1033
+ cl.WriterRaw = caddyconfig.JSONModuleObject(wo, "output", moduleName, h.warnings)
1034
1067
- case "level":
1068
- if !h.NextArg() {
1069
- return nil, h.ArgErr()
1070
- }
1071
- cl.Level = h.Val()
1072
- if h.NextArg() {
1073
- return nil, h.ArgErr()
1074
- }
1035
+ case "format":
1036
+ if !h.NextArg() {
1037
+ return nil, h.ArgErr()
1038
+ }
1039
+ moduleName := h.Val()
1040
+ moduleID := "caddy.logging.encoders." + moduleName
1041
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, moduleID)
1042
+ if err != nil {
1043
+ return nil, err
1044
+ }
1045
+ enc, ok := unm.(zapcore.Encoder)
1046
+ if !ok {
1047
+ return nil, h.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
1048
+ }
1049
+ cl.EncoderRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, h.warnings)
1050
1076
- case "include":
1077
- if !parseAsGlobalOption {
1078
- return nil, h.Err("include is not allowed in the log directive")
1079
- }
1080
- for h.NextArg() {
1081
- cl.Include = append(cl.Include, h.Val())
1082
- }
1051
+ case "level":
1052
+ if !h.NextArg() {
1053
+ return nil, h.ArgErr()
1054
+ }
1055
+ cl.Level = h.Val()
1056
+ if h.NextArg() {
1057
+ return nil, h.ArgErr()
1058
+ }
1059
1084
- case "exclude":
1085
- if !parseAsGlobalOption {
1086
- return nil, h.Err("exclude is not allowed in the log directive")
1087
- }
1088
- for h.NextArg() {
1089
- cl.Exclude = append(cl.Exclude, h.Val())
1090
- }
1060
+ case "include":
1061
+ if !parseAsGlobalOption {
1062
+ return nil, h.Err("include is not allowed in the log directive")
1063
+ }
1064
+ for h.NextArg() {
1065
+ cl.Include = append(cl.Include, h.Val())
1066
+ }
1067
1092
- default:
1093
- return nil, h.Errf("unrecognized subdirective: %s", h.Val())
1068
+ case "exclude":
1069
+ if !parseAsGlobalOption {
1070
+ return nil, h.Err("exclude is not allowed in the log directive")
1071
+ }
1072
+ for h.NextArg() {
1073
+ cl.Exclude = append(cl.Exclude, h.Val())
1074
}
1075
+
1076
+ default:
1077
+ return nil, h.Errf("unrecognized subdirective: %s", h.Val())
1078
}
1079
+ }
1080
1097
- var val namedCustomLog
1098
- val.hostnames = customHostnames
1081
+ var val namedCustomLog
1082
+ val.hostnames = customHostnames
1083
1100
- isEmptyConfig := reflect.DeepEqual(cl, new(caddy.CustomLog))
1084
+ isEmptyConfig := reflect.DeepEqual(cl, new(caddy.CustomLog))
1085
1102
- // Skip handling of empty logging configs
1086
+ // Skip handling of empty logging configs
1087
1104
- if parseAsGlobalOption {
1105
- // Use indicated name for global log options
1088
+ if parseAsGlobalOption {
1089
+ // Use indicated name for global log options
1090
+ val.name = logName
1091
+ } else {
1092
+ if logName != "" {
1093
val.name = logName
1107
- } else {
1108
- if logName != "" {
1109
- val.name = logName
1110
- } else if !isEmptyConfig {
1111
- // Construct a log name for server log streams
1112
- logCounter, ok := h.State["logCounter"].(int)
1113
- if !ok {
1114
- logCounter = 0
1115
- }
1116
- val.name = fmt.Sprintf("log%d", logCounter)
1117
- logCounter++
1118
- h.State["logCounter"] = logCounter
1119
- }
1120
- if val.name != "" {
1121
- cl.Include = []string{"http.log.access." + val.name}
1094
+ } else if !isEmptyConfig {
1095
+ // Construct a log name for server log streams
1096
+ logCounter, ok := h.State["logCounter"].(int)
1097
+ if !ok {
1098
+ logCounter = 0
1099
}
1100
+ val.name = fmt.Sprintf("log%d", logCounter)
1101
+ logCounter++
1102
+ h.State["logCounter"] = logCounter
1103
}
1124
- if !isEmptyConfig {
1125
- val.log = cl
1104
+ if val.name != "" {
1105
+ cl.Include = []string{"http.log.access." + val.name}
1106
}
1127
- configValues = append(configValues, ConfigValue{
1128
- Class: "custom_log",
1129
- Value: val,
1130
- })
1107
}
1108
+ if !isEmptyConfig {
1109
+ val.log = cl
1110
+ }
1111
+ configValues = append(configValues, ConfigValue{
1112
+ Class: "custom_log",
1113
+ Value: val,
1114
+ })
1115
return configValues, nil
1116
}
1117
@@ -1136,10 +1119,9 @@ func parseLogHelper(h Helper, globalLogNames map[string]struct{}) ([]ConfigValue
1119
//
1120
// skip_log [<matcher>]
1121
func parseSkipLog(h Helper) (caddyhttp.MiddlewareHandler, error) {
1139
- for h.Next() {
1140
- if h.NextArg() {
1141
- return nil, h.ArgErr()
1142
- }
1122
+ h.Next() // consume directive name
1123
+ if h.NextArg() {
1124
+ return nil, h.ArgErr()
1125
}
1126
return caddyhttp.VarsMiddleware{"skip_log": true}, nil
1127
}
caddyconfig/httpcaddyfile/directives.go
-6
@@ -271,12 +271,6 @@ func (h Helper) GroupRoutes(vals []ConfigValue) {
271
}
272
}
273
274
-// NewBindAddresses returns config values relevant to adding
275
-// listener bind addresses to the config.
276
-func (h Helper) NewBindAddresses(addrs []string) []ConfigValue {
277
- return []ConfigValue{{Class: "bind", Value: addrs}}
278
-}
279
-
274
// WithDispenser returns a new instance based on d. All others Helper
275
// fields are copied, so typically maps are shared with this new instance.
276
func (h Helper) WithDispenser(d *caddyfile.Dispenser) Helper {
caddyconfig/httpcaddyfile/httptype.go
+57
-52
@@ -1381,68 +1381,73 @@ func (st *ServerType) compileEncodedMatcherSets(sblock serverBlock) ([]caddy.Mod
1381
}
1382
1383
func parseMatcherDefinitions(d *caddyfile.Dispenser, matchers map[string]caddy.ModuleMap) error {
1384
- for d.Next() {
1385
- // this is the "name" for "named matchers"
1386
- definitionName := d.Val()
1384
+ d.Next() // advance to the first token
1385
1388
- if _, ok := matchers[definitionName]; ok {
1389
- return fmt.Errorf("matcher is defined more than once: %s", definitionName)
1386
+ // this is the "name" for "named matchers"
1387
+ definitionName := d.Val()
1388
+
1389
+ if _, ok := matchers[definitionName]; ok {
1390
+ return fmt.Errorf("matcher is defined more than once: %s", definitionName)
1391
+ }
1392
+ matchers[definitionName] = make(caddy.ModuleMap)
1393
+
1394
+ // given a matcher name and the tokens following it, parse
1395
+ // the tokens as a matcher module and record it
1396
+ makeMatcher := func(matcherName string, tokens []caddyfile.Token) error {
1397
+ mod, err := caddy.GetModule("http.matchers." + matcherName)
1398
+ if err != nil {
1399
+ return fmt.Errorf("getting matcher module '%s': %v", matcherName, err)
1400
}
1391
- matchers[definitionName] = make(caddy.ModuleMap)
1401
+ unm, ok := mod.New().(caddyfile.Unmarshaler)
1402
+ if !ok {
1403
+ return fmt.Errorf("matcher module '%s' is not a Caddyfile unmarshaler", matcherName)
1404
+ }
1405
+ err = unm.UnmarshalCaddyfile(caddyfile.NewDispenser(tokens))
1406
+ if err != nil {
1407
+ return err
1408
+ }
1409
+ rm, ok := unm.(caddyhttp.RequestMatcher)
1410
+ if !ok {
1411
+ return fmt.Errorf("matcher module '%s' is not a request matcher", matcherName)
1412
+ }
1413
+ matchers[definitionName][matcherName] = caddyconfig.JSON(rm, nil)
1414
+ return nil
1415
+ }
1416
1393
- // given a matcher name and the tokens following it, parse
1394
- // the tokens as a matcher module and record it
1395
- makeMatcher := func(matcherName string, tokens []caddyfile.Token) error {
1396
- mod, err := caddy.GetModule("http.matchers." + matcherName)
1397
- if err != nil {
1398
- return fmt.Errorf("getting matcher module '%s': %v", matcherName, err)
1399
- }
1400
- unm, ok := mod.New().(caddyfile.Unmarshaler)
1401
- if !ok {
1402
- return fmt.Errorf("matcher module '%s' is not a Caddyfile unmarshaler", matcherName)
1403
- }
1404
- err = unm.UnmarshalCaddyfile(caddyfile.NewDispenser(tokens))
1417
+ // if the next token is quoted, we can assume it's not a matcher name
1418
+ // and that it's probably an 'expression' matcher
1419
+ if d.NextArg() {
1420
+ if d.Token().Quoted() {
1421
+ // since it was missing the matcher name, we insert a token
1422
+ // in front of the expression token itself
1423
+ err := makeMatcher("expression", []caddyfile.Token{
1424
+ {Text: "expression", File: d.File(), Line: d.Line()},
1425
+ d.Token(),
1426
+ })
1427
if err != nil {
1428
return err
1429
}
1408
- rm, ok := unm.(caddyhttp.RequestMatcher)
1409
- if !ok {
1410
- return fmt.Errorf("matcher module '%s' is not a request matcher", matcherName)
1411
- }
1412
- matchers[definitionName][matcherName] = caddyconfig.JSON(rm, nil)
1430
return nil
1431
}
1432
1416
- // if the next token is quoted, we can assume it's not a matcher name
1417
- // and that it's probably an 'expression' matcher
1418
- if d.NextArg() {
1419
- if d.Token().Quoted() {
1420
- err := makeMatcher("expression", []caddyfile.Token{d.Token()})
1421
- if err != nil {
1422
- return err
1423
- }
1424
- continue
1425
- }
1426
-
1427
- // if it wasn't quoted, then we need to rewind after calling
1428
- // d.NextArg() so the below properly grabs the matcher name
1429
- d.Prev()
1430
- }
1433
+ // if it wasn't quoted, then we need to rewind after calling
1434
+ // d.NextArg() so the below properly grabs the matcher name
1435
+ d.Prev()
1436
+ }
1437
1432
- // in case there are multiple instances of the same matcher, concatenate
1433
- // their tokens (we expect that UnmarshalCaddyfile should be able to
1434
- // handle more than one segment); otherwise, we'd overwrite other
1435
- // instances of the matcher in this set
1436
- tokensByMatcherName := make(map[string][]caddyfile.Token)
1437
- for nesting := d.Nesting(); d.NextArg() || d.NextBlock(nesting); {
1438
- matcherName := d.Val()
1439
- tokensByMatcherName[matcherName] = append(tokensByMatcherName[matcherName], d.NextSegment()...)
1440
- }
1441
- for matcherName, tokens := range tokensByMatcherName {
1442
- err := makeMatcher(matcherName, tokens)
1443
- if err != nil {
1444
- return err
1445
- }
1438
+ // in case there are multiple instances of the same matcher, concatenate
1439
+ // their tokens (we expect that UnmarshalCaddyfile should be able to
1440
+ // handle more than one segment); otherwise, we'd overwrite other
1441
+ // instances of the matcher in this set
1442
+ tokensByMatcherName := make(map[string][]caddyfile.Token)
1443
+ for nesting := d.Nesting(); d.NextArg() || d.NextBlock(nesting); {
1444
+ matcherName := d.Val()
1445
+ tokensByMatcherName[matcherName] = append(tokensByMatcherName[matcherName], d.NextSegment()...)
1446
+ }
1447
+ for matcherName, tokens := range tokensByMatcherName {
1448
+ err := makeMatcher(matcherName, tokens)
1449
+ if err != nil {
1450
+ return err
1451
}
1452
}
1453
return nil
caddyconfig/httpcaddyfile/options.go
+182
-183
@@ -62,105 +62,103 @@ func init() {
62
func parseOptTrue(d *caddyfile.Dispenser, _ any) (any, error) { return true, nil }
63
64
func parseOptHTTPPort(d *caddyfile.Dispenser, _ any) (any, error) {
65
+ d.Next() // consume option name
66
var httpPort int
66
- for d.Next() {
67
- var httpPortStr string
68
- if !d.AllArgs(&httpPortStr) {
69
- return 0, d.ArgErr()
70
- }
71
- var err error
72
- httpPort, err = strconv.Atoi(httpPortStr)
73
- if err != nil {
74
- return 0, d.Errf("converting port '%s' to integer value: %v", httpPortStr, err)
75
- }
67
+ var httpPortStr string
68
+ if !d.AllArgs(&httpPortStr) {
69
+ return 0, d.ArgErr()
70
+ }
71
+ var err error
72
+ httpPort, err = strconv.Atoi(httpPortStr)
73
+ if err != nil {
74
+ return 0, d.Errf("converting port '%s' to integer value: %v", httpPortStr, err)
75
}
76
return httpPort, nil
77
}
78
79
func parseOptHTTPSPort(d *caddyfile.Dispenser, _ any) (any, error) {
80
+ d.Next() // consume option name
81
var httpsPort int
82
- for d.Next() {
83
- var httpsPortStr string
84
- if !d.AllArgs(&httpsPortStr) {
85
- return 0, d.ArgErr()
86
- }
87
- var err error
88
- httpsPort, err = strconv.Atoi(httpsPortStr)
89
- if err != nil {
90
- return 0, d.Errf("converting port '%s' to integer value: %v", httpsPortStr, err)
91
- }
82
+ var httpsPortStr string
83
+ if !d.AllArgs(&httpsPortStr) {
84
+ return 0, d.ArgErr()
85
+ }
86
+ var err error
87
+ httpsPort, err = strconv.Atoi(httpsPortStr)
88
+ if err != nil {
89
+ return 0, d.Errf("converting port '%s' to integer value: %v", httpsPortStr, err)
90
}
91
return httpsPort, nil
92
}
93
94
func parseOptOrder(d *caddyfile.Dispenser, _ any) (any, error) {
97
- newOrder := directiveOrder
95
+ d.Next() // consume option name
96
99
- for d.Next() {
100
- // get directive name
101
- if !d.Next() {
102
- return nil, d.ArgErr()
103
- }
104
- dirName := d.Val()
105
- if _, ok := registeredDirectives[dirName]; !ok {
106
- return nil, d.Errf("%s is not a registered directive", dirName)
107
- }
97
+ // get directive name
98
+ if !d.Next() {
99
+ return nil, d.ArgErr()
100
+ }
101
+ dirName := d.Val()
102
+ if _, ok := registeredDirectives[dirName]; !ok {
103
+ return nil, d.Errf("%s is not a registered directive", dirName)
104
+ }
105
109
- // get positional token
110
- if !d.Next() {
111
- return nil, d.ArgErr()
112
- }
113
- pos := d.Val()
106
+ // get positional token
107
+ if !d.Next() {
108
+ return nil, d.ArgErr()
109
+ }
110
+ pos := d.Val()
111
115
- // if directive exists, first remove it
116
- for i, d := range newOrder {
117
- if d == dirName {
118
- newOrder = append(newOrder[:i], newOrder[i+1:]...)
119
- break
120
- }
121
- }
112
+ newOrder := directiveOrder
113
123
- // act on the positional
124
- switch pos {
125
- case "first":
126
- newOrder = append([]string{dirName}, newOrder...)
127
- if d.NextArg() {
128
- return nil, d.ArgErr()
129
- }
130
- directiveOrder = newOrder
131
- return newOrder, nil
132
- case "last":
133
- newOrder = append(newOrder, dirName)
134
- if d.NextArg() {
135
- return nil, d.ArgErr()
136
- }
137
- directiveOrder = newOrder
138
- return newOrder, nil
139
- case "before":
140
- case "after":
141
- default:
142
- return nil, d.Errf("unknown positional '%s'", pos)
114
+ // if directive exists, first remove it
115
+ for i, d := range newOrder {
116
+ if d == dirName {
117
+ newOrder = append(newOrder[:i], newOrder[i+1:]...)
118
+ break
119
}
120
+ }
121
145
- // get name of other directive
146
- if !d.NextArg() {
122
+ // act on the positional
123
+ switch pos {
124
+ case "first":
125
+ newOrder = append([]string{dirName}, newOrder...)
126
+ if d.NextArg() {
127
return nil, d.ArgErr()
128
}
149
- otherDir := d.Val()
129
+ directiveOrder = newOrder
130
+ return newOrder, nil
131
+ case "last":
132
+ newOrder = append(newOrder, dirName)
133
if d.NextArg() {
134
return nil, d.ArgErr()
135
}
136
+ directiveOrder = newOrder
137
+ return newOrder, nil
138
+ case "before":
139
+ case "after":
140
+ default:
141
+ return nil, d.Errf("unknown positional '%s'", pos)
142
+ }
143
+
144
+ // get name of other directive
145
+ if !d.NextArg() {
146
+ return nil, d.ArgErr()
147
+ }
148
+ otherDir := d.Val()
149
+ if d.NextArg() {
150
+ return nil, d.ArgErr()
151
+ }
152
154
- // insert directive into proper position
155
- for i, d := range newOrder {
156
- if d == otherDir {
157
- if pos == "before" {
158
- newOrder = append(newOrder[:i], append([]string{dirName}, newOrder[i:]...)...)
159
- } else if pos == "after" {
160
- newOrder = append(newOrder[:i+1], append([]string{dirName}, newOrder[i+1:]...)...)
161
- }
162
- break
153
+ // insert directive into proper position
154
+ for i, d := range newOrder {
155
+ if d == otherDir {
156
+ if pos == "before" {
157
+ newOrder = append(newOrder[:i], append([]string{dirName}, newOrder[i:]...)...)
158
+ } else if pos == "after" {
159
+ newOrder = append(newOrder[:i+1], append([]string{dirName}, newOrder[i+1:]...)...)
160
}
161
+ break
162
}
163
}
164
@@ -223,57 +221,58 @@ func parseOptACMEDNS(d *caddyfile.Dispenser, _ any) (any, error) {
221
222
func parseOptACMEEAB(d *caddyfile.Dispenser, _ any) (any, error) {
223
eab := new(acme.EAB)
226
- for d.Next() {
227
- if d.NextArg() {
228
- return nil, d.ArgErr()
229
- }
230
- for nesting := d.Nesting(); d.NextBlock(nesting); {
231
- switch d.Val() {
232
- case "key_id":
233
- if !d.NextArg() {
234
- return nil, d.ArgErr()
235
- }
236
- eab.KeyID = d.Val()
237
-
238
- case "mac_key":
239
- if !d.NextArg() {
240
- return nil, d.ArgErr()
241
- }
242
- eab.MACKey = d.Val()
243
-
244
- default:
245
- return nil, d.Errf("unrecognized parameter '%s'", d.Val())
224
+ d.Next() // consume option name
225
+ if d.NextArg() {
226
+ return nil, d.ArgErr()
227
+ }
228
+ for d.NextBlock(0) {
229
+ switch d.Val() {
230
+ case "key_id":
231
+ if !d.NextArg() {
232
+ return nil, d.ArgErr()
233
+ }
234
+ eab.KeyID = d.Val()
235
+
236
+ case "mac_key":
237
+ if !d.NextArg() {
238
+ return nil, d.ArgErr()
239
}
240
+ eab.MACKey = d.Val()
241
+
242
+ default:
243
+ return nil, d.Errf("unrecognized parameter '%s'", d.Val())
244
}
245
}
246
return eab, nil
247
}
248
249
func parseOptCertIssuer(d *caddyfile.Dispenser, existing any) (any, error) {
250
+ d.Next() // consume option name
251
+
252
var issuers []certmagic.Issuer
253
if existing != nil {
254
issuers = existing.([]certmagic.Issuer)
255
}
257
- for d.Next() { // consume option name
258
- if !d.Next() { // get issuer module name
259
- return nil, d.ArgErr()
260
- }
261
- modID := "tls.issuance." + d.Val()
262
- unm, err := caddyfile.UnmarshalModule(d, modID)
263
- if err != nil {
264
- return nil, err
265
- }
266
- iss, ok := unm.(certmagic.Issuer)
267
- if !ok {
268
- return nil, d.Errf("module %s (%T) is not a certmagic.Issuer", modID, unm)
269
- }
270
- issuers = append(issuers, iss)
256
+
257
+ // get issuer module name
258
+ if !d.Next() {
259
+ return nil, d.ArgErr()
260
+ }
261
+ modID := "tls.issuance." + d.Val()
262
+ unm, err := caddyfile.UnmarshalModule(d, modID)
263
+ if err != nil {
264
+ return nil, err
265
+ }
266
+ iss, ok := unm.(certmagic.Issuer)
267
+ if !ok {
268
+ return nil, d.Errf("module %s (%T) is not a certmagic.Issuer", modID, unm)
269
}
270
+ issuers = append(issuers, iss)
271
return issuers, nil
272
}
273
274
func parseOptSingleString(d *caddyfile.Dispenser, _ any) (any, error) {
276
- d.Next() // consume parameter name
275
+ d.Next() // consume option name
276
if !d.Next() {
277
return "", d.ArgErr()
278
}
@@ -285,7 +284,7 @@ func parseOptSingleString(d *caddyfile.Dispenser, _ any) (any, error) {
284
}
285
286
func parseOptStringList(d *caddyfile.Dispenser, _ any) (any, error) {
288
- d.Next() // consume parameter name
287
+ d.Next() // consume option name
288
val := d.RemainingArgs()
289
if len(val) == 0 {
290
return "", d.ArgErr()
@@ -294,33 +293,33 @@ func parseOptStringList(d *caddyfile.Dispenser, _ any) (any, error) {
293
}
294
295
func parseOptAdmin(d *caddyfile.Dispenser, _ any) (any, error) {
296
+ d.Next() // consume option name
297
+
298
adminCfg := new(caddy.AdminConfig)
298
- for d.Next() {
299
- if d.NextArg() {
300
- listenAddress := d.Val()
301
- if listenAddress == "off" {
302
- adminCfg.Disabled = true
303
- if d.Next() { // Do not accept any remaining options including block
304
- return nil, d.Err("No more option is allowed after turning off admin config")
305
- }
306
- } else {
307
- adminCfg.Listen = listenAddress
308
- if d.NextArg() { // At most 1 arg is allowed
309
- return nil, d.ArgErr()
310
- }
299
+ if d.NextArg() {
300
+ listenAddress := d.Val()
301
+ if listenAddress == "off" {
302
+ adminCfg.Disabled = true
303
+ if d.Next() { // Do not accept any remaining options including block
304
+ return nil, d.Err("No more option is allowed after turning off admin config")
305
+ }
306
+ } else {
307
+ adminCfg.Listen = listenAddress
308
+ if d.NextArg() { // At most 1 arg is allowed
309
+ return nil, d.ArgErr()
310
}
311
}
313
- for nesting := d.Nesting(); d.NextBlock(nesting); {
314
- switch d.Val() {
315
- case "enforce_origin":
316
- adminCfg.EnforceOrigin = true
312
+ }
313
+ for d.NextBlock(0) {
314
+ switch d.Val() {
315
+ case "enforce_origin":
316
+ adminCfg.EnforceOrigin = true
317
318
- case "origins":
319
- adminCfg.Origins = d.RemainingArgs()
318
+ case "origins":
319
+ adminCfg.Origins = d.RemainingArgs()
320
321
- default:
322
- return nil, d.Errf("unrecognized parameter '%s'", d.Val())
323
- }
321
+ default:
322
+ return nil, d.Errf("unrecognized parameter '%s'", d.Val())
323
}
324
}
325
if adminCfg.Listen == "" && !adminCfg.Disabled {
@@ -330,57 +329,57 @@ func parseOptAdmin(d *caddyfile.Dispenser, _ any) (any, error) {
329
}
330
331
func parseOptOnDemand(d *caddyfile.Dispenser, _ any) (any, error) {
332
+ d.Next() // consume option name
333
+ if d.NextArg() {
334
+ return nil, d.ArgErr()
335
+ }
336
+
337
var ond *caddytls.OnDemandConfig
334
- for d.Next() {
335
- if d.NextArg() {
336
- return nil, d.ArgErr()
337
- }
338
- for nesting := d.Nesting(); d.NextBlock(nesting); {
339
- switch d.Val() {
340
- case "ask":
341
- if !d.NextArg() {
342
- return nil, d.ArgErr()
343
- }
344
- if ond == nil {
345
- ond = new(caddytls.OnDemandConfig)
346
- }
347
- ond.Ask = d.Val()
348
-
349
- case "interval":
350
- if !d.NextArg() {
351
- return nil, d.ArgErr()
352
- }
353
- dur, err := caddy.ParseDuration(d.Val())
354
- if err != nil {
355
- return nil, err
356
- }
357
- if ond == nil {
358
- ond = new(caddytls.OnDemandConfig)
359
- }
360
- if ond.RateLimit == nil {
361
- ond.RateLimit = new(caddytls.RateLimit)
362
- }
363
- ond.RateLimit.Interval = caddy.Duration(dur)
364
-
365
- case "burst":
366
- if !d.NextArg() {
367
- return nil, d.ArgErr()
368
- }
369
- burst, err := strconv.Atoi(d.Val())
370
- if err != nil {
371
- return nil, err
372
- }
373
- if ond == nil {
374
- ond = new(caddytls.OnDemandConfig)
375
- }
376
- if ond.RateLimit == nil {
377
- ond.RateLimit = new(caddytls.RateLimit)
378
- }
379
- ond.RateLimit.Burst = burst
380
-
381
- default:
382
- return nil, d.Errf("unrecognized parameter '%s'", d.Val())
338
+ for d.NextBlock(0) {
339
+ switch d.Val() {
340
+ case "ask":
341
+ if !d.NextArg() {
342
+ return nil, d.ArgErr()
343
+ }
344
+ if ond == nil {
345
+ ond = new(caddytls.OnDemandConfig)
346
+ }
347
+ ond.Ask = d.Val()
348
+
349
+ case "interval":
350
+ if !d.NextArg() {
351
+ return nil, d.ArgErr()
352
+ }
353
+ dur, err := caddy.ParseDuration(d.Val())
354
+ if err != nil {
355
+ return nil, err
356
}
357
+ if ond == nil {
358
+ ond = new(caddytls.OnDemandConfig)
359
+ }
360
+ if ond.RateLimit == nil {
361
+ ond.RateLimit = new(caddytls.RateLimit)
362
+ }
363
+ ond.RateLimit.Interval = caddy.Duration(dur)
364
+
365
+ case "burst":
366
+ if !d.NextArg() {
367
+ return nil, d.ArgErr()
368
+ }
369
+ burst, err := strconv.Atoi(d.Val())
370
+ if err != nil {
371
+ return nil, err
372
+ }
373
+ if ond == nil {
374
+ ond = new(caddytls.OnDemandConfig)
375
+ }
376
+ if ond.RateLimit == nil {
377
+ ond.RateLimit = new(caddytls.RateLimit)
378
+ }
379
+ ond.RateLimit.Burst = burst
380
+
381
+ default:
382
+ return nil, d.Errf("unrecognized parameter '%s'", d.Val())
383
}
384
}
385
if ond == nil {
@@ -390,7 +389,7 @@ func parseOptOnDemand(d *caddyfile.Dispenser, _ any) (any, error) {
389
}
390
391
func parseOptPersistConfig(d *caddyfile.Dispenser, _ any) (any, error) {
393
- d.Next() // consume parameter name
392
+ d.Next() // consume option name
393
if !d.Next() {
394
return "", d.ArgErr()
395
}
@@ -405,7 +404,7 @@ func parseOptPersistConfig(d *caddyfile.Dispenser, _ any) (any, error) {
404
}
405
406
func parseOptAutoHTTPS(d *caddyfile.Dispenser, _ any) (any, error) {
408
- d.Next() // consume parameter name
407
+ d.Next() // consume option name
408
if !d.Next() {
409
return "", d.ArgErr()
410
}
caddyconfig/httpcaddyfile/pkiapp.go
+98
-98
@@ -48,124 +48,124 @@ func init() {
48
//
49
// When the CA ID is unspecified, 'local' is assumed.
50
func parsePKIApp(d *caddyfile.Dispenser, existingVal any) (any, error) {
51
- pki := &caddypki.PKI{CAs: make(map[string]*caddypki.CA)}
51
+ d.Next() // consume app name
52
53
- for d.Next() {
54
- for nesting := d.Nesting(); d.NextBlock(nesting); {
55
- switch d.Val() {
56
- case "ca":
57
- pkiCa := new(caddypki.CA)
53
+ pki := &caddypki.PKI{
54
+ CAs: make(map[string]*caddypki.CA),
55
+ }
56
+ for d.NextBlock(0) {
57
+ switch d.Val() {
58
+ case "ca":
59
+ pkiCa := new(caddypki.CA)
60
+ if d.NextArg() {
61
+ pkiCa.ID = d.Val()
62
if d.NextArg() {
59
- pkiCa.ID = d.Val()
60
- if d.NextArg() {
63
+ return nil, d.ArgErr()
64
+ }
65
+ }
66
+ if pkiCa.ID == "" {
67
+ pkiCa.ID = caddypki.DefaultCAID
68
+ }
69
+
70
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
71
+ switch d.Val() {
72
+ case "name":
73
+ if !d.NextArg() {
74
return nil, d.ArgErr()
75
}
63
- }
64
- if pkiCa.ID == "" {
65
- pkiCa.ID = caddypki.DefaultCAID
66
- }
76
+ pkiCa.Name = d.Val()
77
68
- for nesting := d.Nesting(); d.NextBlock(nesting); {
69
- switch d.Val() {
70
- case "name":
71
- if !d.NextArg() {
72
- return nil, d.ArgErr()
73
- }
74
- pkiCa.Name = d.Val()
78
+ case "root_cn":
79
+ if !d.NextArg() {
80
+ return nil, d.ArgErr()
81
+ }
82
+ pkiCa.RootCommonName = d.Val()
83
76
- case "root_cn":
77
- if !d.NextArg() {
78
- return nil, d.ArgErr()
79
- }
80
- pkiCa.RootCommonName = d.Val()
84
+ case "intermediate_cn":
85
+ if !d.NextArg() {
86
+ return nil, d.ArgErr()
87
+ }
88
+ pkiCa.IntermediateCommonName = d.Val()
89
82
- case "intermediate_cn":
83
- if !d.NextArg() {
84
- return nil, d.ArgErr()
85
- }
86
- pkiCa.IntermediateCommonName = d.Val()
90
+ case "intermediate_lifetime":
91
+ if !d.NextArg() {
92
+ return nil, d.ArgErr()
93
+ }
94
+ dur, err := caddy.ParseDuration(d.Val())
95
+ if err != nil {
96
+ return nil, err
97
+ }
98
+ pkiCa.IntermediateLifetime = caddy.Duration(dur)
99
88
- case "intermediate_lifetime":
89
- if !d.NextArg() {
90
- return nil, d.ArgErr()
91
- }
92
- dur, err := caddy.ParseDuration(d.Val())
93
- if err != nil {
94
- return nil, err
95
- }
96
- pkiCa.IntermediateLifetime = caddy.Duration(dur)
100
+ case "root":
101
+ if pkiCa.Root == nil {
102
+ pkiCa.Root = new(caddypki.KeyPair)
103
+ }
104
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
105
+ switch d.Val() {
106
+ case "cert":
107
+ if !d.NextArg() {
108
+ return nil, d.ArgErr()
109
+ }
110
+ pkiCa.Root.Certificate = d.Val()
111
98
- case "root":
99
- if pkiCa.Root == nil {
100
- pkiCa.Root = new(caddypki.KeyPair)
101
- }
102
- for nesting := d.Nesting(); d.NextBlock(nesting); {
103
- switch d.Val() {
104
- case "cert":
105
- if !d.NextArg() {
106
- return nil, d.ArgErr()
107
- }
108
- pkiCa.Root.Certificate = d.Val()
109
-
110
- case "key":
111
- if !d.NextArg() {
112
- return nil, d.ArgErr()
113
- }
114
- pkiCa.Root.PrivateKey = d.Val()
115
-
116
- case "format":
117
- if !d.NextArg() {
118
- return nil, d.ArgErr()
119
- }
120
- pkiCa.Root.Format = d.Val()
121
-
122
- default:
123
- return nil, d.Errf("unrecognized pki ca root option '%s'", d.Val())
112
+ case "key":
113
+ if !d.NextArg() {
114
+ return nil, d.ArgErr()
115
}
125
- }
116
+ pkiCa.Root.PrivateKey = d.Val()
117
127
- case "intermediate":
128
- if pkiCa.Intermediate == nil {
129
- pkiCa.Intermediate = new(caddypki.KeyPair)
130
- }
131
- for nesting := d.Nesting(); d.NextBlock(nesting); {
132
- switch d.Val() {
133
- case "cert":
134
- if !d.NextArg() {
135
- return nil, d.ArgErr()
136
- }
137
- pkiCa.Intermediate.Certificate = d.Val()
138
-
139
- case "key":
140
- if !d.NextArg() {
141
- return nil, d.ArgErr()
142
- }
143
- pkiCa.Intermediate.PrivateKey = d.Val()
144
-
145
- case "format":
146
- if !d.NextArg() {
147
- return nil, d.ArgErr()
148
- }
149
- pkiCa.Intermediate.Format = d.Val()
150
-
151
- default:
152
- return nil, d.Errf("unrecognized pki ca intermediate option '%s'", d.Val())
118
+ case "format":
119
+ if !d.NextArg() {
120
+ return nil, d.ArgErr()
121
}
122
+ pkiCa.Root.Format = d.Val()
123
+
124
+ default:
125
+ return nil, d.Errf("unrecognized pki ca root option '%s'", d.Val())
126
}
127
+ }
128
156
- default:
157
- return nil, d.Errf("unrecognized pki ca option '%s'", d.Val())
129
+ case "intermediate":
130
+ if pkiCa.Intermediate == nil {
131
+ pkiCa.Intermediate = new(caddypki.KeyPair)
132
}
159
- }
133
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
134
+ switch d.Val() {
135
+ case "cert":
136
+ if !d.NextArg() {
137
+ return nil, d.ArgErr()
138
+ }
139
+ pkiCa.Intermediate.Certificate = d.Val()
140
161
- pki.CAs[pkiCa.ID] = pkiCa
141
+ case "key":
142
+ if !d.NextArg() {
143
+ return nil, d.ArgErr()
144
+ }
145
+ pkiCa.Intermediate.PrivateKey = d.Val()
146
163
- default:
164
- return nil, d.Errf("unrecognized pki option '%s'", d.Val())
147
+ case "format":
148
+ if !d.NextArg() {
149
+ return nil, d.ArgErr()
150
+ }
151
+ pkiCa.Intermediate.Format = d.Val()
152
+
153
+ default:
154
+ return nil, d.Errf("unrecognized pki ca intermediate option '%s'", d.Val())
155
+ }
156
+ }
157
+
158
+ default:
159
+ return nil, d.Errf("unrecognized pki ca option '%s'", d.Val())
160
+ }
161
}
162
+
163
+ pki.CAs[pkiCa.ID] = pkiCa
164
+
165
+ default:
166
+ return nil, d.Errf("unrecognized pki option '%s'", d.Val())
167
}
168
}
168
-
169
return pki, nil
170
}
171
caddyconfig/httpcaddyfile/serveroptions.go
+200
-200
@@ -53,235 +53,235 @@ type serverOptions struct {
53
}
54
55
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
56
+ d.Next() // consume option name
57
+
58
serverOpts := serverOptions{}
57
- for d.Next() {
59
+ if d.NextArg() {
60
+ serverOpts.ListenerAddress = d.Val()
61
if d.NextArg() {
59
- serverOpts.ListenerAddress = d.Val()
60
- if d.NextArg() {
62
+ return nil, d.ArgErr()
63
+ }
64
+ }
65
+ for d.NextBlock(0) {
66
+ switch d.Val() {
67
+ case "name":
68
+ if serverOpts.ListenerAddress == "" {
69
+ return nil, d.Errf("cannot set a name for a server without a listener address")
70
+ }
71
+ if !d.NextArg() {
72
return nil, d.ArgErr()
73
}
63
- }
64
- for nesting := d.Nesting(); d.NextBlock(nesting); {
65
- switch d.Val() {
66
- case "name":
67
- if serverOpts.ListenerAddress == "" {
68
- return nil, d.Errf("cannot set a name for a server without a listener address")
74
+ serverOpts.Name = d.Val()
75
+
76
+ case "listener_wrappers":
77
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
78
+ modID := "caddy.listeners." + d.Val()
79
+ unm, err := caddyfile.UnmarshalModule(d, modID)
80
+ if err != nil {
81
+ return nil, err
82
}
70
- if !d.NextArg() {
71
- return nil, d.ArgErr()
83
+ listenerWrapper, ok := unm.(caddy.ListenerWrapper)
84
+ if !ok {
85
+ return nil, fmt.Errorf("module %s (%T) is not a listener wrapper", modID, unm)
86
}
73
- serverOpts.Name = d.Val()
87
+ jsonListenerWrapper := caddyconfig.JSONModuleObject(
88
+ listenerWrapper,
89
+ "wrapper",
90
+ listenerWrapper.(caddy.Module).CaddyModule().ID.Name(),
91
+ nil,
92
+ )
93
+ serverOpts.ListenerWrappersRaw = append(serverOpts.ListenerWrappersRaw, jsonListenerWrapper)
94
+ }
95
75
- case "listener_wrappers":
76
- for nesting := d.Nesting(); d.NextBlock(nesting); {
77
- modID := "caddy.listeners." + d.Val()
78
- unm, err := caddyfile.UnmarshalModule(d, modID)
96
+ case "timeouts":
97
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
98
+ switch d.Val() {
99
+ case "read_body":
100
+ if !d.NextArg() {
101
+ return nil, d.ArgErr()
102
+ }
103
+ dur, err := caddy.ParseDuration(d.Val())
104
if err != nil {
80
- return nil, err
105
+ return nil, d.Errf("parsing read_body timeout duration: %v", err)
106
}
82
- listenerWrapper, ok := unm.(caddy.ListenerWrapper)
83
- if !ok {
84
- return nil, fmt.Errorf("module %s (%T) is not a listener wrapper", modID, unm)
107
+ serverOpts.ReadTimeout = caddy.Duration(dur)
108
+
109
+ case "read_header":
110
+ if !d.NextArg() {
111
+ return nil, d.ArgErr()
112
}
86
- jsonListenerWrapper := caddyconfig.JSONModuleObject(
87
- listenerWrapper,
88
- "wrapper",
89
- listenerWrapper.(caddy.Module).CaddyModule().ID.Name(),
90
- nil,
91
- )
92
- serverOpts.ListenerWrappersRaw = append(serverOpts.ListenerWrappersRaw, jsonListenerWrapper)
93
- }
113
+ dur, err := caddy.ParseDuration(d.Val())
114
+ if err != nil {
115
+ return nil, d.Errf("parsing read_header timeout duration: %v", err)
116
+ }
117
+ serverOpts.ReadHeaderTimeout = caddy.Duration(dur)
118
95
- case "timeouts":
96
- for nesting := d.Nesting(); d.NextBlock(nesting); {
97
- switch d.Val() {
98
- case "read_body":
99
- if !d.NextArg() {
100
- return nil, d.ArgErr()
101
- }
102
- dur, err := caddy.ParseDuration(d.Val())
103
- if err != nil {
104
- return nil, d.Errf("parsing read_body timeout duration: %v", err)
105
- }
106
- serverOpts.ReadTimeout = caddy.Duration(dur)
107
-
108
- case "read_header":
109
- if !d.NextArg() {
110
- return nil, d.ArgErr()
111
- }
112
- dur, err := caddy.ParseDuration(d.Val())
113
- if err != nil {
114
- return nil, d.Errf("parsing read_header timeout duration: %v", err)
115
- }
116
- serverOpts.ReadHeaderTimeout = caddy.Duration(dur)
117
-
118
- case "write":
119
- if !d.NextArg() {
120
- return nil, d.ArgErr()
121
- }
122
- dur, err := caddy.ParseDuration(d.Val())
123
- if err != nil {
124
- return nil, d.Errf("parsing write timeout duration: %v", err)
125
- }
126
- serverOpts.WriteTimeout = caddy.Duration(dur)
127
-
128
- case "idle":
129
- if !d.NextArg() {
130
- return nil, d.ArgErr()
131
- }
132
- dur, err := caddy.ParseDuration(d.Val())
133
- if err != nil {
134
- return nil, d.Errf("parsing idle timeout duration: %v", err)
135
- }
136
- serverOpts.IdleTimeout = caddy.Duration(dur)
137
-
138
- default:
139
- return nil, d.Errf("unrecognized timeouts option '%s'", d.Val())
119
+ case "write":
120
+ if !d.NextArg() {
121
+ return nil, d.ArgErr()
122
}
141
- }
142
- case "keepalive_interval":
143
- if !d.NextArg() {
144
- return nil, d.ArgErr()
145
- }
146
- dur, err := caddy.ParseDuration(d.Val())
147
- if err != nil {
148
- return nil, d.Errf("parsing keepalive interval duration: %v", err)
149
- }
150
- serverOpts.KeepAliveInterval = caddy.Duration(dur)
123
+ dur, err := caddy.ParseDuration(d.Val())
124
+ if err != nil {
125
+ return nil, d.Errf("parsing write timeout duration: %v", err)
126
+ }
127
+ serverOpts.WriteTimeout = caddy.Duration(dur)
128
152
- case "max_header_size":
153
- var sizeStr string
154
- if !d.AllArgs(&sizeStr) {
155
- return nil, d.ArgErr()
156
- }
157
- size, err := humanize.ParseBytes(sizeStr)
158
- if err != nil {
159
- return nil, d.Errf("parsing max_header_size: %v", err)
160
- }
161
- serverOpts.MaxHeaderBytes = int(size)
129
+ case "idle":
130
+ if !d.NextArg() {
131
+ return nil, d.ArgErr()
132
+ }
133
+ dur, err := caddy.ParseDuration(d.Val())
134
+ if err != nil {
135
+ return nil, d.Errf("parsing idle timeout duration: %v", err)
136
+ }
137
+ serverOpts.IdleTimeout = caddy.Duration(dur)
138
163
- case "enable_full_duplex":
164
- if d.NextArg() {
165
- return nil, d.ArgErr()
139
+ default:
140
+ return nil, d.Errf("unrecognized timeouts option '%s'", d.Val())
141
}
167
- serverOpts.EnableFullDuplex = true
142
+ }
143
+ case "keepalive_interval":
144
+ if !d.NextArg() {
145
+ return nil, d.ArgErr()
146
+ }
147
+ dur, err := caddy.ParseDuration(d.Val())
148
+ if err != nil {
149
+ return nil, d.Errf("parsing keepalive interval duration: %v", err)
150
+ }
151
+ serverOpts.KeepAliveInterval = caddy.Duration(dur)
152
169
- case "log_credentials":
170
- if d.NextArg() {
171
- return nil, d.ArgErr()
172
- }
173
- serverOpts.ShouldLogCredentials = true
153
+ case "max_header_size":
154
+ var sizeStr string
155
+ if !d.AllArgs(&sizeStr) {
156
+ return nil, d.ArgErr()
157
+ }
158
+ size, err := humanize.ParseBytes(sizeStr)
159
+ if err != nil {
160
+ return nil, d.Errf("parsing max_header_size: %v", err)
161
+ }
162
+ serverOpts.MaxHeaderBytes = int(size)
163
175
- case "protocols":
176
- protos := d.RemainingArgs()
177
- for _, proto := range protos {
178
- if proto != "h1" && proto != "h2" && proto != "h2c" && proto != "h3" {
179
- return nil, d.Errf("unknown protocol '%s': expected h1, h2, h2c, or h3", proto)
180
- }
181
- if sliceContains(serverOpts.Protocols, proto) {
182
- return nil, d.Errf("protocol %s specified more than once", proto)
183
- }
184
- serverOpts.Protocols = append(serverOpts.Protocols, proto)
185
- }
186
- if nesting := d.Nesting(); d.NextBlock(nesting) {
187
- return nil, d.ArgErr()
188
- }
164
+ case "enable_full_duplex":
165
+ if d.NextArg() {
166
+ return nil, d.ArgErr()
167
+ }
168
+ serverOpts.EnableFullDuplex = true
169
190
- case "strict_sni_host":
191
- if d.NextArg() && d.Val() != "insecure_off" && d.Val() != "on" {
192
- return nil, d.Errf("strict_sni_host only supports 'on' or 'insecure_off', got '%s'", d.Val())
193
- }
194
- boolVal := true
195
- if d.Val() == "insecure_off" {
196
- boolVal = false
197
- }
198
- serverOpts.StrictSNIHost = &boolVal
170
+ case "log_credentials":
171
+ if d.NextArg() {
172
+ return nil, d.ArgErr()
173
+ }
174
+ serverOpts.ShouldLogCredentials = true
175
200
- case "trusted_proxies":
201
- if !d.NextArg() {
202
- return nil, d.Err("trusted_proxies expects an IP range source module name as its first argument")
203
- }
204
- modID := "http.ip_sources." + d.Val()
205
- unm, err := caddyfile.UnmarshalModule(d, modID)
206
- if err != nil {
207
- return nil, err
176
+ case "protocols":
177
+ protos := d.RemainingArgs()
178
+ for _, proto := range protos {
179
+ if proto != "h1" && proto != "h2" && proto != "h2c" && proto != "h3" {
180
+ return nil, d.Errf("unknown protocol '%s': expected h1, h2, h2c, or h3", proto)
181
}
209
- source, ok := unm.(caddyhttp.IPRangeSource)
210
- if !ok {
211
- return nil, fmt.Errorf("module %s (%T) is not an IP range source", modID, unm)
182
+ if sliceContains(serverOpts.Protocols, proto) {
183
+ return nil, d.Errf("protocol %s specified more than once", proto)
184
}
213
- jsonSource := caddyconfig.JSONModuleObject(
214
- source,
215
- "source",
216
- source.(caddy.Module).CaddyModule().ID.Name(),
217
- nil,
218
- )
219
- serverOpts.TrustedProxiesRaw = jsonSource
185
+ serverOpts.Protocols = append(serverOpts.Protocols, proto)
186
+ }
187
+ if nesting := d.Nesting(); d.NextBlock(nesting) {
188
+ return nil, d.ArgErr()
189
+ }
190
+
191
+ case "strict_sni_host":
192
+ if d.NextArg() && d.Val() != "insecure_off" && d.Val() != "on" {
193
+ return nil, d.Errf("strict_sni_host only supports 'on' or 'insecure_off', got '%s'", d.Val())
194
+ }
195
+ boolVal := true
196
+ if d.Val() == "insecure_off" {
197
+ boolVal = false
198
+ }
199
+ serverOpts.StrictSNIHost = &boolVal
200
+
201
+ case "trusted_proxies":
202
+ if !d.NextArg() {
203
+ return nil, d.Err("trusted_proxies expects an IP range source module name as its first argument")
204
+ }
205
+ modID := "http.ip_sources." + d.Val()
206
+ unm, err := caddyfile.UnmarshalModule(d, modID)
207
+ if err != nil {
208
+ return nil, err
209
+ }
210
+ source, ok := unm.(caddyhttp.IPRangeSource)
211
+ if !ok {
212
+ return nil, fmt.Errorf("module %s (%T) is not an IP range source", modID, unm)
213
+ }
214
+ jsonSource := caddyconfig.JSONModuleObject(
215
+ source,
216
+ "source",
217
+ source.(caddy.Module).CaddyModule().ID.Name(),
218
+ nil,
219
+ )
220
+ serverOpts.TrustedProxiesRaw = jsonSource
221
+
222
+ case "trusted_proxies_strict":
223
+ if d.NextArg() {
224
+ return nil, d.ArgErr()
225
+ }
226
+ serverOpts.TrustedProxiesStrict = 1
227
221
- case "trusted_proxies_strict":
222
- if d.NextArg() {
223
- return nil, d.ArgErr()
228
+ case "client_ip_headers":
229
+ headers := d.RemainingArgs()
230
+ for _, header := range headers {
231
+ if sliceContains(serverOpts.ClientIPHeaders, header) {
232
+ return nil, d.Errf("client IP header %s specified more than once", header)
233
}
225
- serverOpts.TrustedProxiesStrict = 1
234
+ serverOpts.ClientIPHeaders = append(serverOpts.ClientIPHeaders, header)
235
+ }
236
+ if nesting := d.Nesting(); d.NextBlock(nesting) {
237
+ return nil, d.ArgErr()
238
+ }
239
+
240
+ case "metrics":
241
+ if d.NextArg() {
242
+ return nil, d.ArgErr()
243
+ }
244
+ if nesting := d.Nesting(); d.NextBlock(nesting) {
245
+ return nil, d.ArgErr()
246
+ }
247
+ serverOpts.Metrics = new(caddyhttp.Metrics)
248
+
249
+ // TODO: DEPRECATED. (August 2022)
250
+ case "protocol":
251
+ caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol sub-option will be removed soon")
252
227
- case "client_ip_headers":
228
- headers := d.RemainingArgs()
229
- for _, header := range headers {
230
- if sliceContains(serverOpts.ClientIPHeaders, header) {
231
- return nil, d.Errf("client IP header %s specified more than once", header)
253
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
254
+ switch d.Val() {
255
+ case "allow_h2c":
256
+ caddy.Log().Named("caddyfile").Warn("DEPRECATED: allow_h2c will be removed soon; use protocols option instead")
257
+
258
+ if d.NextArg() {
259
+ return nil, d.ArgErr()
260
}
233
- serverOpts.ClientIPHeaders = append(serverOpts.ClientIPHeaders, header)
234
- }
235
- if nesting := d.Nesting(); d.NextBlock(nesting) {
236
- return nil, d.ArgErr()
237
- }
261
+ if sliceContains(serverOpts.Protocols, "h2c") {
262
+ return nil, d.Errf("protocol h2c already specified")
263
+ }
264
+ serverOpts.Protocols = append(serverOpts.Protocols, "h2c")
265
239
- case "metrics":
240
- if d.NextArg() {
241
- return nil, d.ArgErr()
242
- }
243
- if nesting := d.Nesting(); d.NextBlock(nesting) {
244
- return nil, d.ArgErr()
245
- }
246
- serverOpts.Metrics = new(caddyhttp.Metrics)
247
-
248
- // TODO: DEPRECATED. (August 2022)
249
- case "protocol":
250
- caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol sub-option will be removed soon")
251
-
252
- for nesting := d.Nesting(); d.NextBlock(nesting); {
253
- switch d.Val() {
254
- case "allow_h2c":
255
- caddy.Log().Named("caddyfile").Warn("DEPRECATED: allow_h2c will be removed soon; use protocols option instead")
256
-
257
- if d.NextArg() {
258
- return nil, d.ArgErr()
259
- }
260
- if sliceContains(serverOpts.Protocols, "h2c") {
261
- return nil, d.Errf("protocol h2c already specified")
262
- }
263
- serverOpts.Protocols = append(serverOpts.Protocols, "h2c")
264
-
265
- case "strict_sni_host":
266
- caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol > strict_sni_host in this position will be removed soon; move up to the servers block instead")
267
-
268
- if d.NextArg() && d.Val() != "insecure_off" && d.Val() != "on" {
269
- return nil, d.Errf("strict_sni_host only supports 'on' or 'insecure_off', got '%s'", d.Val())
270
- }
271
- boolVal := true
272
- if d.Val() == "insecure_off" {
273
- boolVal = false
274
- }
275
- serverOpts.StrictSNIHost = &boolVal
276
-
277
- default:
278
- return nil, d.Errf("unrecognized protocol option '%s'", d.Val())
266
+ case "strict_sni_host":
267
+ caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol > strict_sni_host in this position will be removed soon; move up to the servers block instead")
268
+
269
+ if d.NextArg() && d.Val() != "insecure_off" && d.Val() != "on" {
270
+ return nil, d.Errf("strict_sni_host only supports 'on' or 'insecure_off', got '%s'", d.Val())
271
}
280
- }
272
+ boolVal := true
273
+ if d.Val() == "insecure_off" {
274
+ boolVal = false
275
+ }
276
+ serverOpts.StrictSNIHost = &boolVal
277
282
- default:
283
- return nil, d.Errf("unrecognized servers option '%s'", d.Val())
278
+ default:
279
+ return nil, d.Errf("unrecognized protocol option '%s'", d.Val())
280
+ }
281
}
282
+
283
+ default:
284
+ return nil, d.Errf("unrecognized servers option '%s'", d.Val())
285
}
286
}
287
return serverOpts, nil
caddytest/integration/caddyfile_adapt/push.txt
new
+78
@@ -0,0 +1,78 @@
1
+:80
2
+
3
+push * /foo.txt
4
+
5
+push {
6
+ GET /foo.txt
7
+}
8
+
9
+push {
10
+ GET /foo.txt
11
+ HEAD /foo.txt
12
+}
13
+
14
+push {
15
+ headers {
16
+ Foo bar
17
+ }
18
+}
19
+----------
20
+{
21
+ "apps": {
22
+ "http": {
23
+ "servers": {
24
+ "srv0": {
25
+ "listen": [
26
+ ":80"
27
+ ],
28
+ "routes": [
29
+ {
30
+ "handle": [
31
+ {
32
+ "handler": "push",
33
+ "resources": [
34
+ {
35
+ "target": "/foo.txt"
36
+ }
37
+ ]
38
+ },
39
+ {
40
+ "handler": "push",
41
+ "resources": [
42
+ {
43
+ "method": "GET",
44
+ "target": "/foo.txt"
45
+ }
46
+ ]
47
+ },
48
+ {
49
+ "handler": "push",
50
+ "resources": [
51
+ {
52
+ "method": "GET",
53
+ "target": "/foo.txt"
54
+ },
55
+ {
56
+ "method": "HEAD",
57
+ "target": "/foo.txt"
58
+ }
59
+ ]
60
+ },
61
+ {
62
+ "handler": "push",
63
+ "headers": {
64
+ "set": {
65
+ "Foo": [
66
+ "bar"
67
+ ]
68
+ }
69
+ }
70
+ }
71
+ ]
72
+ }
73
+ ]
74
+ }
75
+ }
76
+ }
77
+ }
78
+}
\ No newline at end of file
modules/caddyevents/eventsconfig/caddyfile.go
+1
-7
@@ -40,14 +40,8 @@ func init() {
40
//
41
// If <event> is *, then it will bind to all events.
42
func parseApp(d *caddyfile.Dispenser, _ any) (any, error) {
43
+ d.Next() // consume option name
44
app := new(caddyevents.App)
44
-
45
- // consume the option name
46
- if !d.Next() {
47
- return nil, d.ArgErr()
48
- }
49
-
50
- // handle the block
45
for d.NextBlock(0) {
46
switch d.Val() {
47
case "on":
modules/caddyhttp/caddyauth/caddyfile.go
+40
-40
@@ -34,56 +34,56 @@ func init() {
34
//
35
// If no hash algorithm is supplied, bcrypt will be assumed.
36
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
37
+ h.Next() // consume directive name
38
+
39
var ba HTTPBasicAuth
40
ba.HashCache = new(Cache)
41
40
- for h.Next() {
41
- var cmp Comparer
42
- args := h.RemainingArgs()
42
+ var cmp Comparer
43
+ args := h.RemainingArgs()
44
44
- var hashName string
45
- switch len(args) {
46
- case 0:
47
- hashName = "bcrypt"
48
- case 1:
49
- hashName = args[0]
50
- case 2:
51
- hashName = args[0]
52
- ba.Realm = args[1]
53
- default:
54
- return nil, h.ArgErr()
55
- }
56
-
57
- switch hashName {
58
- case "bcrypt":
59
- cmp = BcryptHash{}
60
- case "scrypt":
61
- cmp = ScryptHash{}
62
- default:
63
- return nil, h.Errf("unrecognized hash algorithm: %s", hashName)
64
- }
45
+ var hashName string
46
+ switch len(args) {
47
+ case 0:
48
+ hashName = "bcrypt"
49
+ case 1:
50
+ hashName = args[0]
51
+ case 2:
52
+ hashName = args[0]
53
+ ba.Realm = args[1]
54
+ default:
55
+ return nil, h.ArgErr()
56
+ }
57
66
- ba.HashRaw = caddyconfig.JSONModuleObject(cmp, "algorithm", hashName, nil)
58
+ switch hashName {
59
+ case "bcrypt":
60
+ cmp = BcryptHash{}
61
+ case "scrypt":
62
+ cmp = ScryptHash{}
63
+ default:
64
+ return nil, h.Errf("unrecognized hash algorithm: %s", hashName)
65
+ }
66
68
- for h.NextBlock(0) {
69
- username := h.Val()
67
+ ba.HashRaw = caddyconfig.JSONModuleObject(cmp, "algorithm", hashName, nil)
68
71
- var b64Pwd, b64Salt string
72
- h.Args(&b64Pwd, &b64Salt)
73
- if h.NextArg() {
74
- return nil, h.ArgErr()
75
- }
69
+ for h.NextBlock(0) {
70
+ username := h.Val()
71
77
- if username == "" || b64Pwd == "" {
78
- return nil, h.Err("username and password cannot be empty or missing")
79
- }
72
+ var b64Pwd, b64Salt string
73
+ h.Args(&b64Pwd, &b64Salt)
74
+ if h.NextArg() {
75
+ return nil, h.ArgErr()
76
+ }
77
81
- ba.AccountList = append(ba.AccountList, Account{
82
- Username: username,
83
- Password: b64Pwd,
84
- Salt: b64Salt,
85
- })
78
+ if username == "" || b64Pwd == "" {
79
+ return nil, h.Err("username and password cannot be empty or missing")
80
}
81
+
82
+ ba.AccountList = append(ba.AccountList, Account{
83
+ Username: username,
84
+ Password: b64Pwd,
85
+ Salt: b64Salt,
86
+ })
87
}
88
89
return Authentication{
modules/caddyhttp/celmatcher.go
+20
-6
@@ -176,13 +176,27 @@ func (m MatchExpression) Match(r *http.Request) bool {
176
177
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
178
func (m *MatchExpression) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
179
- for d.Next() {
180
- if d.CountRemainingArgs() > 1 {
181
- m.Expr = strings.Join(d.RemainingArgsRaw(), " ")
182
- } else {
183
- m.Expr = d.Val()
184
- }
179
+ d.Next() // consume matcher name
180
+
181
+ // if there's multiple args, then we need to keep the raw
182
+ // tokens because the user may have used quotes within their
183
+ // CEL expression (e.g. strings) and we should retain that
184
+ if d.CountRemainingArgs() > 1 {
185
+ m.Expr = strings.Join(d.RemainingArgsRaw(), " ")
186
+ return nil
187
}
188
+
189
+ // there should at least be one arg
190
+ if !d.NextArg() {
191
+ return d.ArgErr()
192
+ }
193
+
194
+ // if there's only one token, then we can safely grab the
195
+ // cleaned token (no quotes) and use that as the expression
196
+ // because there's no valid CEL expression that is only a
197
+ // quoted string; commonly quotes are used in Caddyfile to
198
+ // define the expression
199
+ m.Expr = d.Val()
200
return nil
201
}
202
modules/caddyhttp/encode/caddyfile.go
+45
-47
@@ -54,62 +54,60 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
54
//
55
// Specifying the formats on the first line will use those formats' defaults.
56
func (enc *Encode) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
57
- var prefer []string
57
+ d.Next() // consume directive name
58
59
- responseMatchers := make(map[string]caddyhttp.ResponseMatcher)
59
+ prefer := []string{}
60
+ for _, arg := range d.RemainingArgs() {
61
+ mod, err := caddy.GetModule("http.encoders." + arg)
62
+ if err != nil {
63
+ return d.Errf("finding encoder module '%s': %v", mod, err)
64
+ }
65
+ encoding, ok := mod.New().(Encoding)
66
+ if !ok {
67
+ return d.Errf("module %s is not an HTTP encoding", mod)
68
+ }
69
+ if enc.EncodingsRaw == nil {
70
+ enc.EncodingsRaw = make(caddy.ModuleMap)
71
+ }
72
+ enc.EncodingsRaw[arg] = caddyconfig.JSON(encoding, nil)
73
+ prefer = append(prefer, arg)
74
+ }
75
61
- for d.Next() {
62
- for _, arg := range d.RemainingArgs() {
63
- mod, err := caddy.GetModule("http.encoders." + arg)
76
+ responseMatchers := make(map[string]caddyhttp.ResponseMatcher)
77
+ for d.NextBlock(0) {
78
+ switch d.Val() {
79
+ case "minimum_length":
80
+ if !d.NextArg() {
81
+ return d.ArgErr()
82
+ }
83
+ minLength, err := strconv.Atoi(d.Val())
84
if err != nil {
65
- return d.Errf("finding encoder module '%s': %v", mod, err)
85
+ return err
86
}
67
- encoding, ok := mod.New().(Encoding)
87
+ enc.MinLength = minLength
88
+ case "match":
89
+ err := caddyhttp.ParseNamedResponseMatcher(d.NewFromNextSegment(), responseMatchers)
90
+ if err != nil {
91
+ return err
92
+ }
93
+ matcher := responseMatchers["match"]
94
+ enc.Matcher = &matcher
95
+ default:
96
+ name := d.Val()
97
+ modID := "http.encoders." + name
98
+ unm, err := caddyfile.UnmarshalModule(d, modID)
99
+ if err != nil {
100
+ return err
101
+ }
102
+ encoding, ok := unm.(Encoding)
103
if !ok {
69
- return d.Errf("module %s is not an HTTP encoding", mod)
104
+ return d.Errf("module %s is not an HTTP encoding; is %T", modID, unm)
105
}
106
if enc.EncodingsRaw == nil {
107
enc.EncodingsRaw = make(caddy.ModuleMap)
108
}
74
- enc.EncodingsRaw[arg] = caddyconfig.JSON(encoding, nil)
75
- prefer = append(prefer, arg)
76
- }
77
-
78
- for d.NextBlock(0) {
79
- switch d.Val() {
80
- case "minimum_length":
81
- if !d.NextArg() {
82
- return d.ArgErr()
83
- }
84
- minLength, err := strconv.Atoi(d.Val())
85
- if err != nil {
86
- return err
87
- }
88
- enc.MinLength = minLength
89
- case "match":
90
- err := caddyhttp.ParseNamedResponseMatcher(d.NewFromNextSegment(), responseMatchers)
91
- if err != nil {
92
- return err
93
- }
94
- matcher := responseMatchers["match"]
95
- enc.Matcher = &matcher
96
- default:
97
- name := d.Val()
98
- modID := "http.encoders." + name
99
- unm, err := caddyfile.UnmarshalModule(d, modID)
100
- if err != nil {
101
- return err
102
- }
103
- encoding, ok := unm.(Encoding)
104
- if !ok {
105
- return d.Errf("module %s is not an HTTP encoding; is %T", modID, unm)
106
- }
107
- if enc.EncodingsRaw == nil {
108
- enc.EncodingsRaw = make(caddy.ModuleMap)
109
- }
110
- enc.EncodingsRaw[name] = caddyconfig.JSON(encoding, nil)
111
- prefer = append(prefer, name)
112
- }
109
+ enc.EncodingsRaw[name] = caddyconfig.JSON(encoding, nil)
110
+ prefer = append(prefer, name)
111
}
112
}
113
modules/caddyhttp/encode/gzip/gzip.go
+9
-10
@@ -44,17 +44,16 @@ func (Gzip) CaddyModule() caddy.ModuleInfo {
44
45
// UnmarshalCaddyfile sets up the handler from Caddyfile tokens.
46
func (g *Gzip) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
47
- for d.Next() {
48
- if !d.NextArg() {
49
- continue
50
- }
51
- levelStr := d.Val()
52
- level, err := strconv.Atoi(levelStr)
53
- if err != nil {
54
- return err
55
- }
56
- g.Level = level
47
+ d.Next() // consume option name
48
+ if !d.NextArg() {
49
+ return nil
50
}
51
+ levelStr := d.Val()
52
+ level, err := strconv.Atoi(levelStr)
53
+ if err != nil {
54
+ return err
55
+ }
56
+ g.Level = level
57
return nil
58
}
59
modules/caddyhttp/fileserver/caddyfile.go
+1
-1
@@ -223,7 +223,7 @@ func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
223
224
// parse out the optional try policy
225
var tryPolicy string
226
- for nesting := h.Nesting(); h.NextBlock(nesting); {
226
+ for h.NextBlock(0) {
227
switch h.Val() {
228
case "policy":
229
if tryPolicy != "" {
modules/caddyhttp/fileserver/matcher.go
+1
@@ -127,6 +127,7 @@ func (MatchFile) CaddyModule() caddy.ModuleInfo {
127
// try_policy first_exist|smallest_size|largest_size|most_recently_modified
128
// }
129
func (m *MatchFile) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
130
+ // iterate to merge multiple matchers into one
131
for d.Next() {
132
m.TryFiles = append(m.TryFiles, d.RemainingArgs()...)
133
for d.NextBlock(0) {
modules/caddyhttp/headers/caddyfile.go
+90
-98
@@ -47,14 +47,12 @@ func init() {
47
// ? conditionally sets a value only if the header field is not already set,
48
// and > sets a field with defer enabled.
49
func parseCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
50
- if !h.Next() {
51
- return nil, h.ArgErr()
52
- }
53
-
50
+ h.Next() // consume directive name
51
matcherSet, err := h.ExtractMatcherSet()
52
if err != nil {
53
return nil, err
54
}
55
+ h.Next() // consume the directive name again (matcher parsing resets)
56
57
makeHandler := func() Handler {
58
return Handler{
@@ -65,73 +63,71 @@ func parseCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
63
}
64
handler, handlerWithRequire := makeHandler(), makeHandler()
65
68
- for h.Next() {
69
- // first see if headers are in the initial line
70
- var hasArgs bool
66
+ // first see if headers are in the initial line
67
+ var hasArgs bool
68
+ if h.NextArg() {
69
+ hasArgs = true
70
+ field := h.Val()
71
+ var value, replacement string
72
if h.NextArg() {
72
- hasArgs = true
73
- field := h.Val()
74
- var value, replacement string
75
- if h.NextArg() {
76
- value = h.Val()
77
- }
78
- if h.NextArg() {
79
- replacement = h.Val()
80
- }
81
- err := applyHeaderOp(
82
- handler.Response.HeaderOps,
83
- handler.Response,
84
- field,
85
- value,
86
- replacement,
87
- )
88
- if err != nil {
89
- return nil, h.Err(err.Error())
90
- }
91
- if len(handler.Response.HeaderOps.Delete) > 0 {
92
- handler.Response.Deferred = true
93
- }
73
+ value = h.Val()
74
}
75
+ if h.NextArg() {
76
+ replacement = h.Val()
77
+ }
78
+ err := applyHeaderOp(
79
+ handler.Response.HeaderOps,
80
+ handler.Response,
81
+ field,
82
+ value,
83
+ replacement,
84
+ )
85
+ if err != nil {
86
+ return nil, h.Err(err.Error())
87
+ }
88
+ if len(handler.Response.HeaderOps.Delete) > 0 {
89
+ handler.Response.Deferred = true
90
+ }
91
+ }
92
96
- // if not, they should be in a block
97
- for h.NextBlock(0) {
98
- field := h.Val()
99
- if field == "defer" {
100
- handler.Response.Deferred = true
101
- continue
102
- }
103
- if hasArgs {
104
- return nil, h.Err("cannot specify headers in both arguments and block") // because it would be weird
105
- }
93
+ // if not, they should be in a block
94
+ for h.NextBlock(0) {
95
+ field := h.Val()
96
+ if field == "defer" {
97
+ handler.Response.Deferred = true
98
+ continue
99
+ }
100
+ if hasArgs {
101
+ return nil, h.Err("cannot specify headers in both arguments and block") // because it would be weird
102
+ }
103
107
- // sometimes it is habitual for users to suffix a field name with a colon,
108
- // as if they were writing a curl command or something; see
109
- // https://caddy.community/t/v2-reverse-proxy-please-add-cors-example-to-the-docs/7349/19
110
- field = strings.TrimSuffix(field, ":")
104
+ // sometimes it is habitual for users to suffix a field name with a colon,
105
+ // as if they were writing a curl command or something; see
106
+ // https://caddy.community/t/v2-reverse-proxy-please-add-cors-example-to-the-docs/7349/19
107
+ field = strings.TrimSuffix(field, ":")
108
112
- var value, replacement string
113
- if h.NextArg() {
114
- value = h.Val()
115
- }
116
- if h.NextArg() {
117
- replacement = h.Val()
118
- }
109
+ var value, replacement string
110
+ if h.NextArg() {
111
+ value = h.Val()
112
+ }
113
+ if h.NextArg() {
114
+ replacement = h.Val()
115
+ }
116
120
- handlerToUse := handler
121
- if strings.HasPrefix(field, "?") {
122
- handlerToUse = handlerWithRequire
123
- }
117
+ handlerToUse := handler
118
+ if strings.HasPrefix(field, "?") {
119
+ handlerToUse = handlerWithRequire
120
+ }
121
125
- err := applyHeaderOp(
126
- handlerToUse.Response.HeaderOps,
127
- handlerToUse.Response,
128
- field,
129
- value,
130
- replacement,
131
- )
132
- if err != nil {
133
- return nil, h.Err(err.Error())
134
- }
122
+ err := applyHeaderOp(
123
+ handlerToUse.Response.HeaderOps,
124
+ handlerToUse.Response,
125
+ field,
126
+ value,
127
+ replacement,
128
+ )
129
+ if err != nil {
130
+ return nil, h.Err(err.Error())
131
}
132
}
133
@@ -151,55 +147,51 @@ func parseCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
147
//
148
// request_header [<matcher>] [[+|-]<field> [<value|regexp>] [<replacement>]]
149
func parseReqHdrCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
154
- if !h.Next() {
155
- return nil, h.ArgErr()
156
- }
157
-
150
+ h.Next() // consume directive name
151
matcherSet, err := h.ExtractMatcherSet()
152
if err != nil {
153
return nil, err
154
}
155
+ h.Next() // consume the directive name again (matcher parsing resets)
156
157
configValues := []httpcaddyfile.ConfigValue{}
158
165
- for h.Next() {
166
- if !h.NextArg() {
167
- return nil, h.ArgErr()
168
- }
169
- field := h.Val()
159
+ if !h.NextArg() {
160
+ return nil, h.ArgErr()
161
+ }
162
+ field := h.Val()
163
171
- hdr := Handler{
172
- Request: &HeaderOps{},
173
- }
164
+ hdr := Handler{
165
+ Request: &HeaderOps{},
166
+ }
167
175
- // sometimes it is habitual for users to suffix a field name with a colon,
176
- // as if they were writing a curl command or something; see
177
- // https://caddy.community/t/v2-reverse-proxy-please-add-cors-example-to-the-docs/7349/19
178
- field = strings.TrimSuffix(field, ":")
168
+ // sometimes it is habitual for users to suffix a field name with a colon,
169
+ // as if they were writing a curl command or something; see
170
+ // https://caddy.community/t/v2-reverse-proxy-please-add-cors-example-to-the-docs/7349/19
171
+ field = strings.TrimSuffix(field, ":")
172
180
- var value, replacement string
181
- if h.NextArg() {
182
- value = h.Val()
183
- }
173
+ var value, replacement string
174
+ if h.NextArg() {
175
+ value = h.Val()
176
+ }
177
+ if h.NextArg() {
178
+ replacement = h.Val()
179
if h.NextArg() {
185
- replacement = h.Val()
186
- if h.NextArg() {
187
- return nil, h.ArgErr()
188
- }
180
+ return nil, h.ArgErr()
181
}
182
+ }
183
191
- if hdr.Request == nil {
192
- hdr.Request = new(HeaderOps)
193
- }
194
- if err := CaddyfileHeaderOp(hdr.Request, field, value, replacement); err != nil {
195
- return nil, h.Err(err.Error())
196
- }
184
+ if hdr.Request == nil {
185
+ hdr.Request = new(HeaderOps)
186
+ }
187
+ if err := CaddyfileHeaderOp(hdr.Request, field, value, replacement); err != nil {
188
+ return nil, h.Err(err.Error())
189
+ }
190
198
- configValues = append(configValues, h.NewRoute(matcherSet, hdr)...)
191
+ configValues = append(configValues, h.NewRoute(matcherSet, hdr)...)
192
200
- if h.NextArg() {
201
- return nil, h.ArgErr()
202
- }
193
+ if h.NextArg() {
194
+ return nil, h.ArgErr()
195
}
196
return configValues, nil
197
}
modules/caddyhttp/ip_matchers.go
+23
-25
@@ -79,24 +79,23 @@ func (MatchRemoteIP) CaddyModule() caddy.ModuleInfo {
79
80
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
81
func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
82
- for d.Next() {
83
- for d.NextArg() {
84
- if d.Val() == "forwarded" {
85
- if len(m.Ranges) > 0 {
86
- return d.Err("if used, 'forwarded' must be first argument")
87
- }
88
- m.Forwarded = true
89
- continue
90
- }
91
- if d.Val() == "private_ranges" {
92
- m.Ranges = append(m.Ranges, PrivateRangesCIDR()...)
93
- continue
82
+ d.Next() // consume matcher name
83
+ for d.NextArg() {
84
+ if d.Val() == "forwarded" {
85
+ if len(m.Ranges) > 0 {
86
+ return d.Err("if used, 'forwarded' must be first argument")
87
}
95
- m.Ranges = append(m.Ranges, d.Val())
88
+ m.Forwarded = true
89
+ continue
90
}
97
- if d.NextBlock(0) {
98
- return d.Err("malformed remote_ip matcher: blocks are not supported")
91
+ if d.Val() == "private_ranges" {
92
+ m.Ranges = append(m.Ranges, PrivateRangesCIDR()...)
93
+ continue
94
}
95
+ m.Ranges = append(m.Ranges, d.Val())
96
+ }
97
+ if d.NextBlock(0) {
98
+ return d.Err("malformed remote_ip matcher: blocks are not supported")
99
}
100
return nil
101
}
@@ -189,17 +188,16 @@ func (MatchClientIP) CaddyModule() caddy.ModuleInfo {
188
189
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
190
func (m *MatchClientIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
192
- for d.Next() {
193
- for d.NextArg() {
194
- if d.Val() == "private_ranges" {
195
- m.Ranges = append(m.Ranges, PrivateRangesCIDR()...)
196
- continue
197
- }
198
- m.Ranges = append(m.Ranges, d.Val())
199
- }
200
- if d.NextBlock(0) {
201
- return d.Err("malformed client_ip matcher: blocks are not supported")
191
+ d.Next() // consume matcher name
192
+ for d.NextArg() {
193
+ if d.Val() == "private_ranges" {
194
+ m.Ranges = append(m.Ranges, PrivateRangesCIDR()...)
195
+ continue
196
}
197
+ m.Ranges = append(m.Ranges, d.Val())
198
+ }
199
+ if d.NextBlock(0) {
200
+ return d.Err("malformed client_ip matcher: blocks are not supported")
201
}
202
return nil
203
}
modules/caddyhttp/map/caddyfile.go
+54
-55
@@ -42,74 +42,73 @@ func init() {
42
// However, for convenience, there may be fewer outputs than destinations and any missing
43
// outputs will be filled in implicitly.
44
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
45
+ h.Next() // consume directive name
46
+
47
var handler Handler
48
47
- for h.Next() {
48
- // source
49
- if !h.NextArg() {
50
- return nil, h.ArgErr()
51
- }
52
- handler.Source = h.Val()
49
+ // source
50
+ if !h.NextArg() {
51
+ return nil, h.ArgErr()
52
+ }
53
+ handler.Source = h.Val()
54
54
- // destinations
55
- handler.Destinations = h.RemainingArgs()
56
- if len(handler.Destinations) == 0 {
57
- return nil, h.Err("missing destination argument(s)")
58
- }
59
- for _, dest := range handler.Destinations {
60
- if shorthand := httpcaddyfile.WasReplacedPlaceholderShorthand(dest); shorthand != "" {
61
- return nil, h.Errf("destination %s conflicts with a Caddyfile placeholder shorthand", shorthand)
62
- }
55
+ // destinations
56
+ handler.Destinations = h.RemainingArgs()
57
+ if len(handler.Destinations) == 0 {
58
+ return nil, h.Err("missing destination argument(s)")
59
+ }
60
+ for _, dest := range handler.Destinations {
61
+ if shorthand := httpcaddyfile.WasReplacedPlaceholderShorthand(dest); shorthand != "" {
62
+ return nil, h.Errf("destination %s conflicts with a Caddyfile placeholder shorthand", shorthand)
63
}
64
+ }
65
65
- // mappings
66
- for h.NextBlock(0) {
67
- // defaults are a special case
68
- if h.Val() == "default" {
69
- if len(handler.Defaults) > 0 {
70
- return nil, h.Err("defaults already defined")
71
- }
72
- handler.Defaults = h.RemainingArgs()
73
- for len(handler.Defaults) < len(handler.Destinations) {
74
- handler.Defaults = append(handler.Defaults, "")
75
- }
76
- continue
77
- }
78
-
79
- // every line maps an input value to one or more outputs
80
- in := h.Val()
81
- var outs []any
82
- for h.NextArg() {
83
- val := h.ScalarVal()
84
- if val == "-" {
85
- outs = append(outs, nil)
86
- } else {
87
- outs = append(outs, val)
88
- }
66
+ // mappings
67
+ for h.NextBlock(0) {
68
+ // defaults are a special case
69
+ if h.Val() == "default" {
70
+ if len(handler.Defaults) > 0 {
71
+ return nil, h.Err("defaults already defined")
72
}
90
-
91
- // cannot have more outputs than destinations
92
- if len(outs) > len(handler.Destinations) {
93
- return nil, h.Err("too many outputs")
73
+ handler.Defaults = h.RemainingArgs()
74
+ for len(handler.Defaults) < len(handler.Destinations) {
75
+ handler.Defaults = append(handler.Defaults, "")
76
}
77
+ continue
78
+ }
79
96
- // for convenience, can have fewer outputs than destinations, but the
97
- // underlying handler won't accept that, so we fill in nil values
98
- for len(outs) < len(handler.Destinations) {
80
+ // every line maps an input value to one or more outputs
81
+ in := h.Val()
82
+ var outs []any
83
+ for h.NextArg() {
84
+ val := h.ScalarVal()
85
+ if val == "-" {
86
outs = append(outs, nil)
100
- }
101
-
102
- // create the mapping
103
- mapping := Mapping{Outputs: outs}
104
- if strings.HasPrefix(in, "~") {
105
- mapping.InputRegexp = in[1:]
87
} else {
107
- mapping.Input = in
88
+ outs = append(outs, val)
89
}
90
+ }
91
110
- handler.Mappings = append(handler.Mappings, mapping)
92
+ // cannot have more outputs than destinations
93
+ if len(outs) > len(handler.Destinations) {
94
+ return nil, h.Err("too many outputs")
95
}
112
- }
96
97
+ // for convenience, can have fewer outputs than destinations, but the
98
+ // underlying handler won't accept that, so we fill in nil values
99
+ for len(outs) < len(handler.Destinations) {
100
+ outs = append(outs, nil)
101
+ }
102
+
103
+ // create the mapping
104
+ mapping := Mapping{Outputs: outs}
105
+ if strings.HasPrefix(in, "~") {
106
+ mapping.InputRegexp = in[1:]
107
+ } else {
108
+ mapping.Input = in
109
+ }
110
+
111
+ handler.Mappings = append(handler.Mappings, mapping)
112
+ }
113
return handler, nil
114
}
modules/caddyhttp/matchers.go
+9
@@ -225,6 +225,7 @@ func (MatchHost) CaddyModule() caddy.ModuleInfo {
225
226
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
227
func (m *MatchHost) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
228
+ // iterate to merge multiple matchers into one
229
for d.Next() {
230
*m = append(*m, d.RemainingArgs()...)
231
if d.NextBlock(0) {
@@ -632,6 +633,7 @@ func (MatchPath) CELLibrary(ctx caddy.Context) (cel.Library, error) {
633
634
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
635
func (m *MatchPath) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
636
+ // iterate to merge multiple matchers into one
637
for d.Next() {
638
*m = append(*m, d.RemainingArgs()...)
639
if d.NextBlock(0) {
@@ -716,6 +718,7 @@ func (MatchMethod) CaddyModule() caddy.ModuleInfo {
718
719
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
720
func (m *MatchMethod) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
721
+ // iterate to merge multiple matchers into one
722
for d.Next() {
723
*m = append(*m, d.RemainingArgs()...)
724
if d.NextBlock(0) {
@@ -770,6 +773,7 @@ func (m *MatchQuery) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
773
if *m == nil {
774
*m = make(map[string][]string)
775
}
776
+ // iterate to merge multiple matchers into one
777
for d.Next() {
778
for _, query := range d.RemainingArgs() {
779
if query == "" {
@@ -868,6 +872,7 @@ func (m *MatchHeader) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
872
if *m == nil {
873
*m = make(map[string][]string)
874
}
875
+ // iterate to merge multiple matchers into one
876
for d.Next() {
877
var field, val string
878
if !d.Args(&field) {
@@ -1002,6 +1007,7 @@ func (m *MatchHeaderRE) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1007
if *m == nil {
1008
*m = make(map[string]*MatchRegexp)
1009
}
1010
+ // iterate to merge multiple matchers into one
1011
for d.Next() {
1012
var first, second, third string
1013
if !d.Args(&first, &second) {
@@ -1166,6 +1172,7 @@ func (m MatchProtocol) Match(r *http.Request) bool {
1172
1173
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
1174
func (m *MatchProtocol) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1175
+ // iterate to merge multiple matchers into one
1176
for d.Next() {
1177
var proto string
1178
if !d.Args(&proto) {
@@ -1207,6 +1214,7 @@ func (MatchNot) CaddyModule() caddy.ModuleInfo {
1214
1215
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
1216
func (m *MatchNot) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1217
+ // iterate to merge multiple matchers into one
1218
for d.Next() {
1219
matcherSet, err := ParseCaddyfileNestedMatcherSet(d)
1220
if err != nil {
@@ -1331,6 +1339,7 @@ func (mre *MatchRegexp) Match(input string, repl *caddy.Replacer) bool {
1339
1340
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
1341
func (mre *MatchRegexp) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1342
+ // iterate to merge multiple matchers into one
1343
for d.Next() {
1344
// If this is the second iteration of the loop
1345
// then there's more than one path_regexp matcher
modules/caddyhttp/proxyprotocol/module.go
+30
-30
@@ -39,40 +39,40 @@ func (ListenerWrapper) CaddyModule() caddy.ModuleInfo {
39
// fallback_policy <policy>
40
// }
41
func (w *ListenerWrapper) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
42
- for d.Next() {
43
- // No same-line options are supported
44
- if d.NextArg() {
45
- return d.ArgErr()
46
- }
42
+ d.Next() // consume wrapper name
43
48
- for d.NextBlock(0) {
49
- switch d.Val() {
50
- case "timeout":
51
- if !d.NextArg() {
52
- return d.ArgErr()
53
- }
54
- dur, err := caddy.ParseDuration(d.Val())
55
- if err != nil {
56
- return d.Errf("parsing proxy_protocol timeout duration: %v", err)
57
- }
58
- w.Timeout = caddy.Duration(dur)
44
+ // No same-line options are supported
45
+ if d.NextArg() {
46
+ return d.ArgErr()
47
+ }
48
60
- case "allow":
61
- w.Allow = append(w.Allow, d.RemainingArgs()...)
62
- case "deny":
63
- w.Deny = append(w.Deny, d.RemainingArgs()...)
64
- case "fallback_policy":
65
- if !d.NextArg() {
66
- return d.ArgErr()
67
- }
68
- p, err := parsePolicy(d.Val())
69
- if err != nil {
70
- return d.WrapErr(err)
71
- }
72
- w.FallbackPolicy = p
73
- default:
49
+ for d.NextBlock(0) {
50
+ switch d.Val() {
51
+ case "timeout":
52
+ if !d.NextArg() {
53
return d.ArgErr()
54
}
55
+ dur, err := caddy.ParseDuration(d.Val())
56
+ if err != nil {
57
+ return d.Errf("parsing proxy_protocol timeout duration: %v", err)
58
+ }
59
+ w.Timeout = caddy.Duration(dur)
60
+
61
+ case "allow":
62
+ w.Allow = append(w.Allow, d.RemainingArgs()...)
63
+ case "deny":
64
+ w.Deny = append(w.Deny, d.RemainingArgs()...)
65
+ case "fallback_policy":
66
+ if !d.NextArg() {
67
+ return d.ArgErr()
68
+ }
69
+ p, err := parsePolicy(d.Val())
70
+ if err != nil {
71
+ return d.WrapErr(err)
72
+ }
73
+ w.FallbackPolicy = p
74
+ default:
75
+ return d.ArgErr()
76
}
77
}
78
return nil
modules/caddyhttp/push/caddyfile.go
+45
-45
@@ -44,63 +44,63 @@ func init() {
44
// Placeholders are accepted in resource and header field
45
// name and value and replacement tokens.
46
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
47
- handler := new(Handler)
48
-
49
- for h.Next() {
50
- if h.NextArg() {
51
- handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
52
- }
47
+ h.Next() // consume directive name
48
54
- // optional block
55
- for outerNesting := h.Nesting(); h.NextBlock(outerNesting); {
56
- switch h.Val() {
57
- case "headers":
58
- if h.NextArg() {
59
- return nil, h.ArgErr()
60
- }
61
- for innerNesting := h.Nesting(); h.NextBlock(innerNesting); {
62
- var err error
49
+ handler := new(Handler)
50
64
- // include current token, which we treat as an argument here
65
- args := []string{h.Val()}
66
- args = append(args, h.RemainingArgs()...)
51
+ // inline resources
52
+ if h.NextArg() {
53
+ handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
54
+ }
55
68
- if handler.Headers == nil {
69
- handler.Headers = new(HeaderConfig)
70
- }
56
+ // optional block
57
+ for h.NextBlock(0) {
58
+ switch h.Val() {
59
+ case "headers":
60
+ if h.NextArg() {
61
+ return nil, h.ArgErr()
62
+ }
63
+ for nesting := h.Nesting(); h.NextBlock(nesting); {
64
+ var err error
65
72
- switch len(args) {
73
- case 1:
74
- err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], "", "")
75
- case 2:
76
- err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], args[1], "")
77
- case 3:
78
- err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], args[1], args[2])
79
- default:
80
- return nil, h.ArgErr()
81
- }
66
+ // include current token, which we treat as an argument here
67
+ args := []string{h.Val()}
68
+ args = append(args, h.RemainingArgs()...)
69
83
- if err != nil {
84
- return nil, h.Err(err.Error())
85
- }
70
+ if handler.Headers == nil {
71
+ handler.Headers = new(HeaderConfig)
72
}
73
88
- case "GET", "HEAD":
89
- method := h.Val()
90
- if !h.NextArg() {
74
+ switch len(args) {
75
+ case 1:
76
+ err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], "", "")
77
+ case 2:
78
+ err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], args[1], "")
79
+ case 3:
80
+ err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], args[1], args[2])
81
+ default:
82
return nil, h.ArgErr()
83
}
93
- target := h.Val()
94
- handler.Resources = append(handler.Resources, Resource{
95
- Method: method,
96
- Target: target,
97
- })
84
99
- default:
100
- handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
85
+ if err != nil {
86
+ return nil, h.Err(err.Error())
87
+ }
88
+ }
89
+
90
+ case "GET", "HEAD":
91
+ method := h.Val()
92
+ if !h.NextArg() {
93
+ return nil, h.ArgErr()
94
}
95
+ target := h.Val()
96
+ handler.Resources = append(handler.Resources, Resource{
97
+ Method: method,
98
+ Target: target,
99
+ })
100
+
101
+ default:
102
+ handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
103
}
104
}
104
-
105
return handler, nil
106
}
modules/caddyhttp/requestbody/caddyfile.go
+17
-16
@@ -26,25 +26,26 @@ func init() {
26
}
27
28
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
29
+ h.Next() // consume directive name
30
+
31
rb := new(RequestBody)
32
31
- for h.Next() {
32
- // configuration should be in a block
33
- for h.NextBlock(0) {
34
- switch h.Val() {
35
- case "max_size":
36
- var sizeStr string
37
- if !h.AllArgs(&sizeStr) {
38
- return nil, h.ArgErr()
39
- }
40
- size, err := humanize.ParseBytes(sizeStr)
41
- if err != nil {
42
- return nil, h.Errf("parsing max_size: %v", err)
43
- }
44
- rb.MaxSize = int64(size)
45
- default:
46
- return nil, h.Errf("unrecognized servers option '%s'", h.Val())
33
+ // configuration should be in a block
34
+ for h.NextBlock(0) {
35
+ switch h.Val() {
36
+ case "max_size":
37
+ var sizeStr string
38
+ if !h.AllArgs(&sizeStr) {
39
+ return nil, h.ArgErr()
40
+ }
41
+ size, err := humanize.ParseBytes(sizeStr)
42
+ if err != nil {
43
+ return nil, h.Errf("parsing max_size: %v", err)
44
}
45
+ rb.MaxSize = int64(size)
46
+
47
+ default:
48
+ return nil, h.Errf("unrecognized servers option '%s'", h.Val())
49
}
50
}
51
modules/caddyhttp/responsematchers.go
+38
-40
@@ -67,55 +67,53 @@ func (rm ResponseMatcher) matchStatusCode(statusCode int) bool {
67
//
68
// @name [header <field> [<value>]] | [status <code...>]
69
func ParseNamedResponseMatcher(d *caddyfile.Dispenser, matchers map[string]ResponseMatcher) error {
70
- for d.Next() {
71
- definitionName := d.Val()
70
+ d.Next() // consume matcher name
71
+ definitionName := d.Val()
72
73
- if _, ok := matchers[definitionName]; ok {
74
- return d.Errf("matcher is defined more than once: %s", definitionName)
75
- }
73
+ if _, ok := matchers[definitionName]; ok {
74
+ return d.Errf("matcher is defined more than once: %s", definitionName)
75
+ }
76
77
- matcher := ResponseMatcher{}
78
- for nesting := d.Nesting(); d.NextArg() || d.NextBlock(nesting); {
79
- switch d.Val() {
80
- case "header":
81
- if matcher.Headers == nil {
82
- matcher.Headers = http.Header{}
83
- }
77
+ matcher := ResponseMatcher{}
78
+ for nesting := d.Nesting(); d.NextArg() || d.NextBlock(nesting); {
79
+ switch d.Val() {
80
+ case "header":
81
+ if matcher.Headers == nil {
82
+ matcher.Headers = http.Header{}
83
+ }
84
85
- // reuse the header request matcher's unmarshaler
86
- headerMatcher := MatchHeader(matcher.Headers)
87
- err := headerMatcher.UnmarshalCaddyfile(d.NewFromNextSegment())
88
- if err != nil {
89
- return err
90
- }
85
+ // reuse the header request matcher's unmarshaler
86
+ headerMatcher := MatchHeader(matcher.Headers)
87
+ err := headerMatcher.UnmarshalCaddyfile(d.NewFromNextSegment())
88
+ if err != nil {
89
+ return err
90
+ }
91
92
- matcher.Headers = http.Header(headerMatcher)
93
- case "status":
94
- if matcher.StatusCode == nil {
95
- matcher.StatusCode = []int{}
96
- }
92
+ matcher.Headers = http.Header(headerMatcher)
93
+ case "status":
94
+ if matcher.StatusCode == nil {
95
+ matcher.StatusCode = []int{}
96
+ }
97
98
- args := d.RemainingArgs()
99
- if len(args) == 0 {
100
- return d.ArgErr()
101
- }
98
+ args := d.RemainingArgs()
99
+ if len(args) == 0 {
100
+ return d.ArgErr()
101
+ }
102
103
- for _, arg := range args {
104
- if len(arg) == 3 && strings.HasSuffix(arg, "xx") {
105
- arg = arg[:1]
106
- }
107
- statusNum, err := strconv.Atoi(arg)
108
- if err != nil {
109
- return d.Errf("bad status value '%s': %v", arg, err)
110
- }
111
- matcher.StatusCode = append(matcher.StatusCode, statusNum)
103
+ for _, arg := range args {
104
+ if len(arg) == 3 && strings.HasSuffix(arg, "xx") {
105
+ arg = arg[:1]
106
}
113
- default:
114
- return d.Errf("unrecognized response matcher %s", d.Val())
107
+ statusNum, err := strconv.Atoi(arg)
108
+ if err != nil {
109
+ return d.Errf("bad status value '%s': %v", arg, err)
110
+ }
111
+ matcher.StatusCode = append(matcher.StatusCode, statusNum)
112
}
113
+ default:
114
+ return d.Errf("unrecognized response matcher %s", d.Val())
115
}
117
-
118
- matchers[definitionName] = matcher
116
}
117
+ matchers[definitionName] = matcher
118
return nil
119
}
modules/caddyhttp/reverseproxy/caddyfile.go
+465
-469
@@ -210,7 +210,7 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
210
}
211
}
212
213
- for nesting := d.Nesting(); d.NextBlock(nesting); {
213
+ for d.NextBlock(0) {
214
// if the subdirective has an "@" prefix then we
215
// parse it as a response matcher for use with "handle_response"
216
if strings.HasPrefix(d.Val(), matcherPrefix) {
@@ -774,7 +774,7 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
774
}
775
776
// make sure there's no block, cause it doesn't make sense
777
- if d.NextBlock(1) {
777
+ if nesting := d.Nesting(); d.NextBlock(nesting) {
778
return d.Errf("cannot define routes for 'replace_status', use 'handle_response' instead.")
779
}
780
@@ -930,297 +930,296 @@ func (h *Handler) FinalizeUnmarshalCaddyfile(helper httpcaddyfile.Helper) error
930
// max_idle_conns_per_host <count>
931
// }
932
func (h *HTTPTransport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
933
- for d.Next() {
934
- for d.NextBlock(0) {
935
- switch d.Val() {
936
- case "read_buffer":
937
- if !d.NextArg() {
938
- return d.ArgErr()
939
- }
940
- size, err := humanize.ParseBytes(d.Val())
941
- if err != nil {
942
- return d.Errf("invalid read buffer size '%s': %v", d.Val(), err)
943
- }
944
- h.ReadBufferSize = int(size)
945
-
946
- case "write_buffer":
947
- if !d.NextArg() {
948
- return d.ArgErr()
949
- }
950
- size, err := humanize.ParseBytes(d.Val())
951
- if err != nil {
952
- return d.Errf("invalid write buffer size '%s': %v", d.Val(), err)
953
- }
954
- h.WriteBufferSize = int(size)
933
+ d.Next() // consume transport name
934
+ for d.NextBlock(0) {
935
+ switch d.Val() {
936
+ case "read_buffer":
937
+ if !d.NextArg() {
938
+ return d.ArgErr()
939
+ }
940
+ size, err := humanize.ParseBytes(d.Val())
941
+ if err != nil {
942
+ return d.Errf("invalid read buffer size '%s': %v", d.Val(), err)
943
+ }
944
+ h.ReadBufferSize = int(size)
945
956
- case "read_timeout":
957
- if !d.NextArg() {
958
- return d.ArgErr()
959
- }
960
- timeout, err := caddy.ParseDuration(d.Val())
961
- if err != nil {
962
- return d.Errf("invalid read timeout duration '%s': %v", d.Val(), err)
963
- }
964
- h.ReadTimeout = caddy.Duration(timeout)
946
+ case "write_buffer":
947
+ if !d.NextArg() {
948
+ return d.ArgErr()
949
+ }
950
+ size, err := humanize.ParseBytes(d.Val())
951
+ if err != nil {
952
+ return d.Errf("invalid write buffer size '%s': %v", d.Val(), err)
953
+ }
954
+ h.WriteBufferSize = int(size)
955
966
- case "write_timeout":
967
- if !d.NextArg() {
968
- return d.ArgErr()
969
- }
970
- timeout, err := caddy.ParseDuration(d.Val())
971
- if err != nil {
972
- return d.Errf("invalid write timeout duration '%s': %v", d.Val(), err)
973
- }
974
- h.WriteTimeout = caddy.Duration(timeout)
956
+ case "read_timeout":
957
+ if !d.NextArg() {
958
+ return d.ArgErr()
959
+ }
960
+ timeout, err := caddy.ParseDuration(d.Val())
961
+ if err != nil {
962
+ return d.Errf("invalid read timeout duration '%s': %v", d.Val(), err)
963
+ }
964
+ h.ReadTimeout = caddy.Duration(timeout)
965
976
- case "max_response_header":
977
- if !d.NextArg() {
978
- return d.ArgErr()
979
- }
980
- size, err := humanize.ParseBytes(d.Val())
981
- if err != nil {
982
- return d.Errf("invalid max response header size '%s': %v", d.Val(), err)
983
- }
984
- h.MaxResponseHeaderSize = int64(size)
966
+ case "write_timeout":
967
+ if !d.NextArg() {
968
+ return d.ArgErr()
969
+ }
970
+ timeout, err := caddy.ParseDuration(d.Val())
971
+ if err != nil {
972
+ return d.Errf("invalid write timeout duration '%s': %v", d.Val(), err)
973
+ }
974
+ h.WriteTimeout = caddy.Duration(timeout)
975
986
- case "proxy_protocol":
987
- if !d.NextArg() {
988
- return d.ArgErr()
989
- }
990
- switch proxyProtocol := d.Val(); proxyProtocol {
991
- case "v1", "v2":
992
- h.ProxyProtocol = proxyProtocol
993
- default:
994
- return d.Errf("invalid proxy protocol version '%s'", proxyProtocol)
995
- }
976
+ case "max_response_header":
977
+ if !d.NextArg() {
978
+ return d.ArgErr()
979
+ }
980
+ size, err := humanize.ParseBytes(d.Val())
981
+ if err != nil {
982
+ return d.Errf("invalid max response header size '%s': %v", d.Val(), err)
983
+ }
984
+ h.MaxResponseHeaderSize = int64(size)
985
997
- case "dial_timeout":
998
- if !d.NextArg() {
999
- return d.ArgErr()
1000
- }
1001
- dur, err := caddy.ParseDuration(d.Val())
1002
- if err != nil {
1003
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1004
- }
1005
- h.DialTimeout = caddy.Duration(dur)
986
+ case "proxy_protocol":
987
+ if !d.NextArg() {
988
+ return d.ArgErr()
989
+ }
990
+ switch proxyProtocol := d.Val(); proxyProtocol {
991
+ case "v1", "v2":
992
+ h.ProxyProtocol = proxyProtocol
993
+ default:
994
+ return d.Errf("invalid proxy protocol version '%s'", proxyProtocol)
995
+ }
996
1007
- case "dial_fallback_delay":
1008
- if !d.NextArg() {
1009
- return d.ArgErr()
1010
- }
1011
- dur, err := caddy.ParseDuration(d.Val())
1012
- if err != nil {
1013
- return d.Errf("bad fallback delay value '%s': %v", d.Val(), err)
1014
- }
1015
- h.FallbackDelay = caddy.Duration(dur)
997
+ case "dial_timeout":
998
+ if !d.NextArg() {
999
+ return d.ArgErr()
1000
+ }
1001
+ dur, err := caddy.ParseDuration(d.Val())
1002
+ if err != nil {
1003
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1004
+ }
1005
+ h.DialTimeout = caddy.Duration(dur)
1006
1017
- case "response_header_timeout":
1018
- if !d.NextArg() {
1019
- return d.ArgErr()
1020
- }
1021
- dur, err := caddy.ParseDuration(d.Val())
1022
- if err != nil {
1023
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1024
- }
1025
- h.ResponseHeaderTimeout = caddy.Duration(dur)
1007
+ case "dial_fallback_delay":
1008
+ if !d.NextArg() {
1009
+ return d.ArgErr()
1010
+ }
1011
+ dur, err := caddy.ParseDuration(d.Val())
1012
+ if err != nil {
1013
+ return d.Errf("bad fallback delay value '%s': %v", d.Val(), err)
1014
+ }
1015
+ h.FallbackDelay = caddy.Duration(dur)
1016
1027
- case "expect_continue_timeout":
1028
- if !d.NextArg() {
1029
- return d.ArgErr()
1030
- }
1031
- dur, err := caddy.ParseDuration(d.Val())
1032
- if err != nil {
1033
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1034
- }
1035
- h.ExpectContinueTimeout = caddy.Duration(dur)
1017
+ case "response_header_timeout":
1018
+ if !d.NextArg() {
1019
+ return d.ArgErr()
1020
+ }
1021
+ dur, err := caddy.ParseDuration(d.Val())
1022
+ if err != nil {
1023
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1024
+ }
1025
+ h.ResponseHeaderTimeout = caddy.Duration(dur)
1026
1037
- case "resolvers":
1038
- if h.Resolver == nil {
1039
- h.Resolver = new(UpstreamResolver)
1040
- }
1041
- h.Resolver.Addresses = d.RemainingArgs()
1042
- if len(h.Resolver.Addresses) == 0 {
1043
- return d.Errf("must specify at least one resolver address")
1044
- }
1027
+ case "expect_continue_timeout":
1028
+ if !d.NextArg() {
1029
+ return d.ArgErr()
1030
+ }
1031
+ dur, err := caddy.ParseDuration(d.Val())
1032
+ if err != nil {
1033
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1034
+ }
1035
+ h.ExpectContinueTimeout = caddy.Duration(dur)
1036
1046
- case "tls":
1047
- if h.TLS == nil {
1048
- h.TLS = new(TLSConfig)
1049
- }
1037
+ case "resolvers":
1038
+ if h.Resolver == nil {
1039
+ h.Resolver = new(UpstreamResolver)
1040
+ }
1041
+ h.Resolver.Addresses = d.RemainingArgs()
1042
+ if len(h.Resolver.Addresses) == 0 {
1043
+ return d.Errf("must specify at least one resolver address")
1044
+ }
1045
1051
- case "tls_client_auth":
1052
- if h.TLS == nil {
1053
- h.TLS = new(TLSConfig)
1054
- }
1055
- args := d.RemainingArgs()
1056
- switch len(args) {
1057
- case 1:
1058
- h.TLS.ClientCertificateAutomate = args[0]
1059
- case 2:
1060
- h.TLS.ClientCertificateFile = args[0]
1061
- h.TLS.ClientCertificateKeyFile = args[1]
1062
- default:
1063
- return d.ArgErr()
1064
- }
1046
+ case "tls":
1047
+ if h.TLS == nil {
1048
+ h.TLS = new(TLSConfig)
1049
+ }
1050
1066
- case "tls_insecure_skip_verify":
1067
- if d.NextArg() {
1068
- return d.ArgErr()
1069
- }
1070
- if h.TLS == nil {
1071
- h.TLS = new(TLSConfig)
1072
- }
1073
- h.TLS.InsecureSkipVerify = true
1051
+ case "tls_client_auth":
1052
+ if h.TLS == nil {
1053
+ h.TLS = new(TLSConfig)
1054
+ }
1055
+ args := d.RemainingArgs()
1056
+ switch len(args) {
1057
+ case 1:
1058
+ h.TLS.ClientCertificateAutomate = args[0]
1059
+ case 2:
1060
+ h.TLS.ClientCertificateFile = args[0]
1061
+ h.TLS.ClientCertificateKeyFile = args[1]
1062
+ default:
1063
+ return d.ArgErr()
1064
+ }
1065
1075
- case "tls_curves":
1076
- args := d.RemainingArgs()
1077
- if len(args) == 0 {
1078
- return d.ArgErr()
1079
- }
1080
- if h.TLS == nil {
1081
- h.TLS = new(TLSConfig)
1082
- }
1083
- h.TLS.Curves = args
1066
+ case "tls_insecure_skip_verify":
1067
+ if d.NextArg() {
1068
+ return d.ArgErr()
1069
+ }
1070
+ if h.TLS == nil {
1071
+ h.TLS = new(TLSConfig)
1072
+ }
1073
+ h.TLS.InsecureSkipVerify = true
1074
1085
- case "tls_timeout":
1086
- if !d.NextArg() {
1087
- return d.ArgErr()
1088
- }
1089
- dur, err := caddy.ParseDuration(d.Val())
1090
- if err != nil {
1091
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1092
- }
1093
- if h.TLS == nil {
1094
- h.TLS = new(TLSConfig)
1095
- }
1096
- h.TLS.HandshakeTimeout = caddy.Duration(dur)
1075
+ case "tls_curves":
1076
+ args := d.RemainingArgs()
1077
+ if len(args) == 0 {
1078
+ return d.ArgErr()
1079
+ }
1080
+ if h.TLS == nil {
1081
+ h.TLS = new(TLSConfig)
1082
+ }
1083
+ h.TLS.Curves = args
1084
1098
- case "tls_trusted_ca_certs":
1099
- args := d.RemainingArgs()
1100
- if len(args) == 0 {
1101
- return d.ArgErr()
1102
- }
1103
- if h.TLS == nil {
1104
- h.TLS = new(TLSConfig)
1105
- }
1106
- h.TLS.RootCAPEMFiles = args
1085
+ case "tls_timeout":
1086
+ if !d.NextArg() {
1087
+ return d.ArgErr()
1088
+ }
1089
+ dur, err := caddy.ParseDuration(d.Val())
1090
+ if err != nil {
1091
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1092
+ }
1093
+ if h.TLS == nil {
1094
+ h.TLS = new(TLSConfig)
1095
+ }
1096
+ h.TLS.HandshakeTimeout = caddy.Duration(dur)
1097
1108
- case "tls_server_name":
1109
- if !d.NextArg() {
1110
- return d.ArgErr()
1111
- }
1112
- if h.TLS == nil {
1113
- h.TLS = new(TLSConfig)
1114
- }
1115
- h.TLS.ServerName = d.Val()
1098
+ case "tls_trusted_ca_certs":
1099
+ args := d.RemainingArgs()
1100
+ if len(args) == 0 {
1101
+ return d.ArgErr()
1102
+ }
1103
+ if h.TLS == nil {
1104
+ h.TLS = new(TLSConfig)
1105
+ }
1106
+ h.TLS.RootCAPEMFiles = args
1107
1117
- case "tls_renegotiation":
1118
- if h.TLS == nil {
1119
- h.TLS = new(TLSConfig)
1120
- }
1121
- if !d.NextArg() {
1122
- return d.ArgErr()
1123
- }
1124
- switch renegotiation := d.Val(); renegotiation {
1125
- case "never", "once", "freely":
1126
- h.TLS.Renegotiation = renegotiation
1127
- default:
1128
- return d.ArgErr()
1129
- }
1108
+ case "tls_server_name":
1109
+ if !d.NextArg() {
1110
+ return d.ArgErr()
1111
+ }
1112
+ if h.TLS == nil {
1113
+ h.TLS = new(TLSConfig)
1114
+ }
1115
+ h.TLS.ServerName = d.Val()
1116
1131
- case "tls_except_ports":
1132
- if h.TLS == nil {
1133
- h.TLS = new(TLSConfig)
1134
- }
1135
- h.TLS.ExceptPorts = d.RemainingArgs()
1136
- if len(h.TLS.ExceptPorts) == 0 {
1137
- return d.ArgErr()
1138
- }
1117
+ case "tls_renegotiation":
1118
+ if h.TLS == nil {
1119
+ h.TLS = new(TLSConfig)
1120
+ }
1121
+ if !d.NextArg() {
1122
+ return d.ArgErr()
1123
+ }
1124
+ switch renegotiation := d.Val(); renegotiation {
1125
+ case "never", "once", "freely":
1126
+ h.TLS.Renegotiation = renegotiation
1127
+ default:
1128
+ return d.ArgErr()
1129
+ }
1130
1140
- case "keepalive":
1141
- if !d.NextArg() {
1142
- return d.ArgErr()
1143
- }
1144
- if h.KeepAlive == nil {
1145
- h.KeepAlive = new(KeepAlive)
1146
- }
1147
- if d.Val() == "off" {
1148
- var disable bool
1149
- h.KeepAlive.Enabled = &disable
1150
- break
1151
- }
1152
- dur, err := caddy.ParseDuration(d.Val())
1153
- if err != nil {
1154
- return d.Errf("bad duration value '%s': %v", d.Val(), err)
1155
- }
1156
- h.KeepAlive.IdleConnTimeout = caddy.Duration(dur)
1131
+ case "tls_except_ports":
1132
+ if h.TLS == nil {
1133
+ h.TLS = new(TLSConfig)
1134
+ }
1135
+ h.TLS.ExceptPorts = d.RemainingArgs()
1136
+ if len(h.TLS.ExceptPorts) == 0 {
1137
+ return d.ArgErr()
1138
+ }
1139
1158
- case "keepalive_interval":
1159
- if !d.NextArg() {
1160
- return d.ArgErr()
1161
- }
1162
- dur, err := caddy.ParseDuration(d.Val())
1163
- if err != nil {
1164
- return d.Errf("bad interval value '%s': %v", d.Val(), err)
1165
- }
1166
- if h.KeepAlive == nil {
1167
- h.KeepAlive = new(KeepAlive)
1168
- }
1169
- h.KeepAlive.ProbeInterval = caddy.Duration(dur)
1140
+ case "keepalive":
1141
+ if !d.NextArg() {
1142
+ return d.ArgErr()
1143
+ }
1144
+ if h.KeepAlive == nil {
1145
+ h.KeepAlive = new(KeepAlive)
1146
+ }
1147
+ if d.Val() == "off" {
1148
+ var disable bool
1149
+ h.KeepAlive.Enabled = &disable
1150
+ break
1151
+ }
1152
+ dur, err := caddy.ParseDuration(d.Val())
1153
+ if err != nil {
1154
+ return d.Errf("bad duration value '%s': %v", d.Val(), err)
1155
+ }
1156
+ h.KeepAlive.IdleConnTimeout = caddy.Duration(dur)
1157
1171
- case "keepalive_idle_conns":
1172
- if !d.NextArg() {
1173
- return d.ArgErr()
1174
- }
1175
- num, err := strconv.Atoi(d.Val())
1176
- if err != nil {
1177
- return d.Errf("bad integer value '%s': %v", d.Val(), err)
1178
- }
1179
- if h.KeepAlive == nil {
1180
- h.KeepAlive = new(KeepAlive)
1181
- }
1182
- h.KeepAlive.MaxIdleConns = num
1158
+ case "keepalive_interval":
1159
+ if !d.NextArg() {
1160
+ return d.ArgErr()
1161
+ }
1162
+ dur, err := caddy.ParseDuration(d.Val())
1163
+ if err != nil {
1164
+ return d.Errf("bad interval value '%s': %v", d.Val(), err)
1165
+ }
1166
+ if h.KeepAlive == nil {
1167
+ h.KeepAlive = new(KeepAlive)
1168
+ }
1169
+ h.KeepAlive.ProbeInterval = caddy.Duration(dur)
1170
1184
- case "keepalive_idle_conns_per_host":
1185
- if !d.NextArg() {
1186
- return d.ArgErr()
1187
- }
1188
- num, err := strconv.Atoi(d.Val())
1189
- if err != nil {
1190
- return d.Errf("bad integer value '%s': %v", d.Val(), err)
1191
- }
1192
- if h.KeepAlive == nil {
1193
- h.KeepAlive = new(KeepAlive)
1194
- }
1195
- h.KeepAlive.MaxIdleConnsPerHost = num
1171
+ case "keepalive_idle_conns":
1172
+ if !d.NextArg() {
1173
+ return d.ArgErr()
1174
+ }
1175
+ num, err := strconv.Atoi(d.Val())
1176
+ if err != nil {
1177
+ return d.Errf("bad integer value '%s': %v", d.Val(), err)
1178
+ }
1179
+ if h.KeepAlive == nil {
1180
+ h.KeepAlive = new(KeepAlive)
1181
+ }
1182
+ h.KeepAlive.MaxIdleConns = num
1183
1197
- case "versions":
1198
- h.Versions = d.RemainingArgs()
1199
- if len(h.Versions) == 0 {
1200
- return d.ArgErr()
1201
- }
1184
+ case "keepalive_idle_conns_per_host":
1185
+ if !d.NextArg() {
1186
+ return d.ArgErr()
1187
+ }
1188
+ num, err := strconv.Atoi(d.Val())
1189
+ if err != nil {
1190
+ return d.Errf("bad integer value '%s': %v", d.Val(), err)
1191
+ }
1192
+ if h.KeepAlive == nil {
1193
+ h.KeepAlive = new(KeepAlive)
1194
+ }
1195
+ h.KeepAlive.MaxIdleConnsPerHost = num
1196
1203
- case "compression":
1204
- if d.NextArg() {
1205
- if d.Val() == "off" {
1206
- var disable bool
1207
- h.Compression = &disable
1208
- }
1209
- }
1197
+ case "versions":
1198
+ h.Versions = d.RemainingArgs()
1199
+ if len(h.Versions) == 0 {
1200
+ return d.ArgErr()
1201
+ }
1202
1211
- case "max_conns_per_host":
1212
- if !d.NextArg() {
1213
- return d.ArgErr()
1214
- }
1215
- num, err := strconv.Atoi(d.Val())
1216
- if err != nil {
1217
- return d.Errf("bad integer value '%s': %v", d.Val(), err)
1203
+ case "compression":
1204
+ if d.NextArg() {
1205
+ if d.Val() == "off" {
1206
+ var disable bool
1207
+ h.Compression = &disable
1208
}
1219
- h.MaxConnsPerHost = num
1209
+ }
1210
1221
- default:
1222
- return d.Errf("unrecognized subdirective %s", d.Val())
1211
+ case "max_conns_per_host":
1212
+ if !d.NextArg() {
1213
+ return d.ArgErr()
1214
+ }
1215
+ num, err := strconv.Atoi(d.Val())
1216
+ if err != nil {
1217
+ return d.Errf("bad integer value '%s': %v", d.Val(), err)
1218
}
1219
+ h.MaxConnsPerHost = num
1220
+
1221
+ default:
1222
+ return d.Errf("unrecognized subdirective %s", d.Val())
1223
}
1224
}
1225
return nil
@@ -1241,25 +1240,25 @@ func parseCopyResponseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHan
1240
// status <status>
1241
// }
1242
func (h *CopyResponseHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1244
- for d.Next() {
1245
- args := d.RemainingArgs()
1246
- if len(args) == 1 {
1247
- if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
1248
- h.StatusCode = caddyhttp.WeakString(args[0])
1249
- break
1250
- }
1243
+ d.Next() // consume directive name
1244
+
1245
+ args := d.RemainingArgs()
1246
+ if len(args) == 1 {
1247
+ if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
1248
+ h.StatusCode = caddyhttp.WeakString(args[0])
1249
+ return nil
1250
}
1251
+ }
1252
1253
- for d.NextBlock(0) {
1254
- switch d.Val() {
1255
- case "status":
1256
- if !d.NextArg() {
1257
- return d.ArgErr()
1258
- }
1259
- h.StatusCode = caddyhttp.WeakString(d.Val())
1260
- default:
1261
- return d.Errf("unrecognized subdirective '%s'", d.Val())
1253
+ for d.NextBlock(0) {
1254
+ switch d.Val() {
1255
+ case "status":
1256
+ if !d.NextArg() {
1257
+ return d.ArgErr()
1258
}
1259
+ h.StatusCode = caddyhttp.WeakString(d.Val())
1260
+ default:
1261
+ return d.Errf("unrecognized subdirective '%s'", d.Val())
1262
}
1263
}
1264
return nil
@@ -1281,23 +1280,23 @@ func parseCopyResponseHeadersCaddyfile(h httpcaddyfile.Helper) (caddyhttp.Middle
1280
// exclude <fields...>
1281
// }
1282
func (h *CopyResponseHeadersHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1284
- for d.Next() {
1285
- args := d.RemainingArgs()
1286
- if len(args) > 0 {
1287
- return d.ArgErr()
1288
- }
1283
+ d.Next() // consume directive name
1284
1290
- for d.NextBlock(0) {
1291
- switch d.Val() {
1292
- case "include":
1293
- h.Include = append(h.Include, d.RemainingArgs()...)
1285
+ args := d.RemainingArgs()
1286
+ if len(args) > 0 {
1287
+ return d.ArgErr()
1288
+ }
1289
1295
- case "exclude":
1296
- h.Exclude = append(h.Exclude, d.RemainingArgs()...)
1290
+ for d.NextBlock(0) {
1291
+ switch d.Val() {
1292
+ case "include":
1293
+ h.Include = append(h.Include, d.RemainingArgs()...)
1294
1298
- default:
1299
- return d.Errf("unrecognized subdirective '%s'", d.Val())
1300
- }
1295
+ case "exclude":
1296
+ h.Exclude = append(h.Exclude, d.RemainingArgs()...)
1297
+
1298
+ default:
1299
+ return d.Errf("unrecognized subdirective '%s'", d.Val())
1300
}
1301
}
1302
return nil
@@ -1315,89 +1314,88 @@ func (h *CopyResponseHeadersHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser)
1314
// dial_fallback_delay <timeout>
1315
// }
1316
func (u *SRVUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1318
- for d.Next() {
1319
- args := d.RemainingArgs()
1320
- if len(args) > 1 {
1321
- return d.ArgErr()
1322
- }
1323
- if len(args) > 0 {
1324
- u.Name = args[0]
1325
- }
1317
+ d.Next() // consume upstream source name
1318
1327
- for d.NextBlock(0) {
1328
- switch d.Val() {
1329
- case "service":
1330
- if !d.NextArg() {
1331
- return d.ArgErr()
1332
- }
1333
- if u.Service != "" {
1334
- return d.Errf("srv service has already been specified")
1335
- }
1336
- u.Service = d.Val()
1319
+ args := d.RemainingArgs()
1320
+ if len(args) > 1 {
1321
+ return d.ArgErr()
1322
+ }
1323
+ if len(args) > 0 {
1324
+ u.Name = args[0]
1325
+ }
1326
1338
- case "proto":
1339
- if !d.NextArg() {
1340
- return d.ArgErr()
1341
- }
1342
- if u.Proto != "" {
1343
- return d.Errf("srv proto has already been specified")
1344
- }
1345
- u.Proto = d.Val()
1327
+ for d.NextBlock(0) {
1328
+ switch d.Val() {
1329
+ case "service":
1330
+ if !d.NextArg() {
1331
+ return d.ArgErr()
1332
+ }
1333
+ if u.Service != "" {
1334
+ return d.Errf("srv service has already been specified")
1335
+ }
1336
+ u.Service = d.Val()
1337
1347
- case "name":
1348
- if !d.NextArg() {
1349
- return d.ArgErr()
1350
- }
1351
- if u.Name != "" {
1352
- return d.Errf("srv name has already been specified")
1353
- }
1354
- u.Name = d.Val()
1338
+ case "proto":
1339
+ if !d.NextArg() {
1340
+ return d.ArgErr()
1341
+ }
1342
+ if u.Proto != "" {
1343
+ return d.Errf("srv proto has already been specified")
1344
+ }
1345
+ u.Proto = d.Val()
1346
1356
- case "refresh":
1357
- if !d.NextArg() {
1358
- return d.ArgErr()
1359
- }
1360
- dur, err := caddy.ParseDuration(d.Val())
1361
- if err != nil {
1362
- return d.Errf("parsing refresh interval duration: %v", err)
1363
- }
1364
- u.Refresh = caddy.Duration(dur)
1347
+ case "name":
1348
+ if !d.NextArg() {
1349
+ return d.ArgErr()
1350
+ }
1351
+ if u.Name != "" {
1352
+ return d.Errf("srv name has already been specified")
1353
+ }
1354
+ u.Name = d.Val()
1355
1366
- case "resolvers":
1367
- if u.Resolver == nil {
1368
- u.Resolver = new(UpstreamResolver)
1369
- }
1370
- u.Resolver.Addresses = d.RemainingArgs()
1371
- if len(u.Resolver.Addresses) == 0 {
1372
- return d.Errf("must specify at least one resolver address")
1373
- }
1356
+ case "refresh":
1357
+ if !d.NextArg() {
1358
+ return d.ArgErr()
1359
+ }
1360
+ dur, err := caddy.ParseDuration(d.Val())
1361
+ if err != nil {
1362
+ return d.Errf("parsing refresh interval duration: %v", err)
1363
+ }
1364
+ u.Refresh = caddy.Duration(dur)
1365
1375
- case "dial_timeout":
1376
- if !d.NextArg() {
1377
- return d.ArgErr()
1378
- }
1379
- dur, err := caddy.ParseDuration(d.Val())
1380
- if err != nil {
1381
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1382
- }
1383
- u.DialTimeout = caddy.Duration(dur)
1366
+ case "resolvers":
1367
+ if u.Resolver == nil {
1368
+ u.Resolver = new(UpstreamResolver)
1369
+ }
1370
+ u.Resolver.Addresses = d.RemainingArgs()
1371
+ if len(u.Resolver.Addresses) == 0 {
1372
+ return d.Errf("must specify at least one resolver address")
1373
+ }
1374
1385
- case "dial_fallback_delay":
1386
- if !d.NextArg() {
1387
- return d.ArgErr()
1388
- }
1389
- dur, err := caddy.ParseDuration(d.Val())
1390
- if err != nil {
1391
- return d.Errf("bad delay value '%s': %v", d.Val(), err)
1392
- }
1393
- u.FallbackDelay = caddy.Duration(dur)
1375
+ case "dial_timeout":
1376
+ if !d.NextArg() {
1377
+ return d.ArgErr()
1378
+ }
1379
+ dur, err := caddy.ParseDuration(d.Val())
1380
+ if err != nil {
1381
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1382
+ }
1383
+ u.DialTimeout = caddy.Duration(dur)
1384
1395
- default:
1396
- return d.Errf("unrecognized srv option '%s'", d.Val())
1385
+ case "dial_fallback_delay":
1386
+ if !d.NextArg() {
1387
+ return d.ArgErr()
1388
+ }
1389
+ dur, err := caddy.ParseDuration(d.Val())
1390
+ if err != nil {
1391
+ return d.Errf("bad delay value '%s': %v", d.Val(), err)
1392
}
1393
+ u.FallbackDelay = caddy.Duration(dur)
1394
+
1395
+ default:
1396
+ return d.Errf("unrecognized srv option '%s'", d.Val())
1397
}
1398
}
1400
-
1399
return nil
1400
}
1401
@@ -1413,105 +1411,104 @@ func (u *SRVUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1411
// versions ipv4|ipv6
1412
// }
1413
func (u *AUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1416
- for d.Next() {
1417
- args := d.RemainingArgs()
1418
- if len(args) > 2 {
1419
- return d.ArgErr()
1420
- }
1421
- if len(args) > 0 {
1422
- u.Name = args[0]
1423
- if len(args) == 2 {
1424
- u.Port = args[1]
1425
- }
1414
+ d.Next() // consume upstream source name
1415
+
1416
+ args := d.RemainingArgs()
1417
+ if len(args) > 2 {
1418
+ return d.ArgErr()
1419
+ }
1420
+ if len(args) > 0 {
1421
+ u.Name = args[0]
1422
+ if len(args) == 2 {
1423
+ u.Port = args[1]
1424
}
1425
+ }
1426
1428
- for d.NextBlock(0) {
1429
- switch d.Val() {
1430
- case "name":
1431
- if !d.NextArg() {
1432
- return d.ArgErr()
1433
- }
1434
- if u.Name != "" {
1435
- return d.Errf("a name has already been specified")
1436
- }
1437
- u.Name = d.Val()
1427
+ for d.NextBlock(0) {
1428
+ switch d.Val() {
1429
+ case "name":
1430
+ if !d.NextArg() {
1431
+ return d.ArgErr()
1432
+ }
1433
+ if u.Name != "" {
1434
+ return d.Errf("a name has already been specified")
1435
+ }
1436
+ u.Name = d.Val()
1437
1439
- case "port":
1440
- if !d.NextArg() {
1441
- return d.ArgErr()
1442
- }
1443
- if u.Port != "" {
1444
- return d.Errf("a port has already been specified")
1445
- }
1446
- u.Port = d.Val()
1438
+ case "port":
1439
+ if !d.NextArg() {
1440
+ return d.ArgErr()
1441
+ }
1442
+ if u.Port != "" {
1443
+ return d.Errf("a port has already been specified")
1444
+ }
1445
+ u.Port = d.Val()
1446
1448
- case "refresh":
1449
- if !d.NextArg() {
1450
- return d.ArgErr()
1451
- }
1452
- dur, err := caddy.ParseDuration(d.Val())
1453
- if err != nil {
1454
- return d.Errf("parsing refresh interval duration: %v", err)
1455
- }
1456
- u.Refresh = caddy.Duration(dur)
1447
+ case "refresh":
1448
+ if !d.NextArg() {
1449
+ return d.ArgErr()
1450
+ }
1451
+ dur, err := caddy.ParseDuration(d.Val())
1452
+ if err != nil {
1453
+ return d.Errf("parsing refresh interval duration: %v", err)
1454
+ }
1455
+ u.Refresh = caddy.Duration(dur)
1456
1458
- case "resolvers":
1459
- if u.Resolver == nil {
1460
- u.Resolver = new(UpstreamResolver)
1461
- }
1462
- u.Resolver.Addresses = d.RemainingArgs()
1463
- if len(u.Resolver.Addresses) == 0 {
1464
- return d.Errf("must specify at least one resolver address")
1465
- }
1457
+ case "resolvers":
1458
+ if u.Resolver == nil {
1459
+ u.Resolver = new(UpstreamResolver)
1460
+ }
1461
+ u.Resolver.Addresses = d.RemainingArgs()
1462
+ if len(u.Resolver.Addresses) == 0 {
1463
+ return d.Errf("must specify at least one resolver address")
1464
+ }
1465
1467
- case "dial_timeout":
1468
- if !d.NextArg() {
1469
- return d.ArgErr()
1470
- }
1471
- dur, err := caddy.ParseDuration(d.Val())
1472
- if err != nil {
1473
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1474
- }
1475
- u.DialTimeout = caddy.Duration(dur)
1466
+ case "dial_timeout":
1467
+ if !d.NextArg() {
1468
+ return d.ArgErr()
1469
+ }
1470
+ dur, err := caddy.ParseDuration(d.Val())
1471
+ if err != nil {
1472
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
1473
+ }
1474
+ u.DialTimeout = caddy.Duration(dur)
1475
1477
- case "dial_fallback_delay":
1478
- if !d.NextArg() {
1479
- return d.ArgErr()
1480
- }
1481
- dur, err := caddy.ParseDuration(d.Val())
1482
- if err != nil {
1483
- return d.Errf("bad delay value '%s': %v", d.Val(), err)
1484
- }
1485
- u.FallbackDelay = caddy.Duration(dur)
1476
+ case "dial_fallback_delay":
1477
+ if !d.NextArg() {
1478
+ return d.ArgErr()
1479
+ }
1480
+ dur, err := caddy.ParseDuration(d.Val())
1481
+ if err != nil {
1482
+ return d.Errf("bad delay value '%s': %v", d.Val(), err)
1483
+ }
1484
+ u.FallbackDelay = caddy.Duration(dur)
1485
1487
- case "versions":
1488
- args := d.RemainingArgs()
1489
- if len(args) == 0 {
1490
- return d.Errf("must specify at least one version")
1491
- }
1486
+ case "versions":
1487
+ args := d.RemainingArgs()
1488
+ if len(args) == 0 {
1489
+ return d.Errf("must specify at least one version")
1490
+ }
1491
1493
- if u.Versions == nil {
1494
- u.Versions = &IPVersions{}
1495
- }
1492
+ if u.Versions == nil {
1493
+ u.Versions = &IPVersions{}
1494
+ }
1495
1497
- trueBool := true
1498
- for _, arg := range args {
1499
- switch arg {
1500
- case "ipv4":
1501
- u.Versions.IPv4 = &trueBool
1502
- case "ipv6":
1503
- u.Versions.IPv6 = &trueBool
1504
- default:
1505
- return d.Errf("unsupported version: '%s'", arg)
1506
- }
1496
+ trueBool := true
1497
+ for _, arg := range args {
1498
+ switch arg {
1499
+ case "ipv4":
1500
+ u.Versions.IPv4 = &trueBool
1501
+ case "ipv6":
1502
+ u.Versions.IPv6 = &trueBool
1503
+ default:
1504
+ return d.Errf("unsupported version: '%s'", arg)
1505
}
1508
-
1509
- default:
1510
- return d.Errf("unrecognized a option '%s'", d.Val())
1506
}
1507
+
1508
+ default:
1509
+ return d.Errf("unrecognized a option '%s'", d.Val())
1510
}
1511
}
1514
-
1512
return nil
1513
}
1514
@@ -1521,26 +1518,25 @@ func (u *AUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1518
// <source> [...]
1519
// }
1520
func (u *MultiUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
1524
- for d.Next() {
1525
- if d.NextArg() {
1526
- return d.ArgErr()
1527
- }
1521
+ d.Next() // consume upstream source name
1522
1529
- for nesting := d.Nesting(); d.NextBlock(nesting); {
1530
- dynModule := d.Val()
1531
- modID := "http.reverse_proxy.upstreams." + dynModule
1532
- unm, err := caddyfile.UnmarshalModule(d, modID)
1533
- if err != nil {
1534
- return err
1535
- }
1536
- source, ok := unm.(UpstreamSource)
1537
- if !ok {
1538
- return d.Errf("module %s (%T) is not an UpstreamSource", modID, unm)
1539
- }
1540
- u.SourcesRaw = append(u.SourcesRaw, caddyconfig.JSONModuleObject(source, "source", dynModule, nil))
1541
- }
1523
+ if d.NextArg() {
1524
+ return d.ArgErr()
1525
}
1526
1527
+ for d.NextBlock(0) {
1528
+ dynModule := d.Val()
1529
+ modID := "http.reverse_proxy.upstreams." + dynModule
1530
+ unm, err := caddyfile.UnmarshalModule(d, modID)
1531
+ if err != nil {
1532
+ return err
1533
+ }
1534
+ source, ok := unm.(UpstreamSource)
1535
+ if !ok {
1536
+ return d.Errf("module %s (%T) is not an UpstreamSource", modID, unm)
1537
+ }
1538
+ u.SourcesRaw = append(u.SourcesRaw, caddyconfig.JSONModuleObject(source, "source", dynModule, nil))
1539
+ }
1540
return nil
1541
}
1542
modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go
+61
-62
@@ -46,76 +46,75 @@ func init() {
46
// capture_stderr
47
// }
48
func (t *Transport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
49
- for d.Next() {
50
- for d.NextBlock(0) {
51
- switch d.Val() {
52
- case "root":
53
- if !d.NextArg() {
54
- return d.ArgErr()
55
- }
56
- t.Root = d.Val()
57
-
58
- case "split":
59
- t.SplitPath = d.RemainingArgs()
60
- if len(t.SplitPath) == 0 {
61
- return d.ArgErr()
62
- }
49
+ d.Next() // consume transport name
50
+ for d.NextBlock(0) {
51
+ switch d.Val() {
52
+ case "root":
53
+ if !d.NextArg() {
54
+ return d.ArgErr()
55
+ }
56
+ t.Root = d.Val()
57
64
- case "env":
65
- args := d.RemainingArgs()
66
- if len(args) != 2 {
67
- return d.ArgErr()
68
- }
69
- if t.EnvVars == nil {
70
- t.EnvVars = make(map[string]string)
71
- }
72
- t.EnvVars[args[0]] = args[1]
58
+ case "split":
59
+ t.SplitPath = d.RemainingArgs()
60
+ if len(t.SplitPath) == 0 {
61
+ return d.ArgErr()
62
+ }
63
74
- case "resolve_root_symlink":
75
- if d.NextArg() {
76
- return d.ArgErr()
77
- }
78
- t.ResolveRootSymlink = true
64
+ case "env":
65
+ args := d.RemainingArgs()
66
+ if len(args) != 2 {
67
+ return d.ArgErr()
68
+ }
69
+ if t.EnvVars == nil {
70
+ t.EnvVars = make(map[string]string)
71
+ }
72
+ t.EnvVars[args[0]] = args[1]
73
80
- case "dial_timeout":
81
- if !d.NextArg() {
82
- return d.ArgErr()
83
- }
84
- dur, err := caddy.ParseDuration(d.Val())
85
- if err != nil {
86
- return d.Errf("bad timeout value %s: %v", d.Val(), err)
87
- }
88
- t.DialTimeout = caddy.Duration(dur)
74
+ case "resolve_root_symlink":
75
+ if d.NextArg() {
76
+ return d.ArgErr()
77
+ }
78
+ t.ResolveRootSymlink = true
79
90
- case "read_timeout":
91
- if !d.NextArg() {
92
- return d.ArgErr()
93
- }
94
- dur, err := caddy.ParseDuration(d.Val())
95
- if err != nil {
96
- return d.Errf("bad timeout value %s: %v", d.Val(), err)
97
- }
98
- t.ReadTimeout = caddy.Duration(dur)
80
+ case "dial_timeout":
81
+ if !d.NextArg() {
82
+ return d.ArgErr()
83
+ }
84
+ dur, err := caddy.ParseDuration(d.Val())
85
+ if err != nil {
86
+ return d.Errf("bad timeout value %s: %v", d.Val(), err)
87
+ }
88
+ t.DialTimeout = caddy.Duration(dur)
89
100
- case "write_timeout":
101
- if !d.NextArg() {
102
- return d.ArgErr()
103
- }
104
- dur, err := caddy.ParseDuration(d.Val())
105
- if err != nil {
106
- return d.Errf("bad timeout value %s: %v", d.Val(), err)
107
- }
108
- t.WriteTimeout = caddy.Duration(dur)
90
+ case "read_timeout":
91
+ if !d.NextArg() {
92
+ return d.ArgErr()
93
+ }
94
+ dur, err := caddy.ParseDuration(d.Val())
95
+ if err != nil {
96
+ return d.Errf("bad timeout value %s: %v", d.Val(), err)
97
+ }
98
+ t.ReadTimeout = caddy.Duration(dur)
99
110
- case "capture_stderr":
111
- if d.NextArg() {
112
- return d.ArgErr()
113
- }
114
- t.CaptureStderr = true
100
+ case "write_timeout":
101
+ if !d.NextArg() {
102
+ return d.ArgErr()
103
+ }
104
+ dur, err := caddy.ParseDuration(d.Val())
105
+ if err != nil {
106
+ return d.Errf("bad timeout value %s: %v", d.Val(), err)
107
+ }
108
+ t.WriteTimeout = caddy.Duration(dur)
109
116
- default:
117
- return d.Errf("unrecognized subdirective %s", d.Val())
110
+ case "capture_stderr":
111
+ if d.NextArg() {
112
+ return d.ArgErr()
113
}
114
+ t.CaptureStderr = true
115
+
116
+ default:
117
+ return d.Errf("unrecognized subdirective %s", d.Val())
118
}
119
}
120
return nil
modules/caddyhttp/reverseproxy/selectionpolicies.go
+60
-65
@@ -68,10 +68,9 @@ func (r RandomSelection) Select(pool UpstreamPool, request *http.Request, _ http
68
69
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
70
func (r *RandomSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
71
- for d.Next() {
72
- if d.NextArg() {
73
- return d.ArgErr()
74
- }
71
+ d.Next() // consume policy name
72
+ if d.NextArg() {
73
+ return d.ArgErr()
74
}
75
return nil
76
}
@@ -98,22 +97,22 @@ func (WeightedRoundRobinSelection) CaddyModule() caddy.ModuleInfo {
97
98
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
99
func (r *WeightedRoundRobinSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
101
- for d.Next() {
102
- args := d.RemainingArgs()
103
- if len(args) == 0 {
104
- return d.ArgErr()
105
- }
100
+ d.Next() // consume policy name
101
107
- for _, weight := range args {
108
- weightInt, err := strconv.Atoi(weight)
109
- if err != nil {
110
- return d.Errf("invalid weight value '%s': %v", weight, err)
111
- }
112
- if weightInt < 1 {
113
- return d.Errf("invalid weight value '%s': weight should be non-zero and positive", weight)
114
- }
115
- r.Weights = append(r.Weights, weightInt)
102
+ args := d.RemainingArgs()
103
+ if len(args) == 0 {
104
+ return d.ArgErr()
105
+ }
106
+
107
+ for _, weight := range args {
108
+ weightInt, err := strconv.Atoi(weight)
109
+ if err != nil {
110
+ return d.Errf("invalid weight value '%s': %v", weight, err)
111
+ }
112
+ if weightInt < 1 {
113
+ return d.Errf("invalid weight value '%s': weight should be non-zero and positive", weight)
114
}
115
+ r.Weights = append(r.Weights, weightInt)
116
}
117
return nil
118
}
@@ -179,17 +178,17 @@ func (RandomChoiceSelection) CaddyModule() caddy.ModuleInfo {
178
179
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
180
func (r *RandomChoiceSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
182
- for d.Next() {
183
- if !d.NextArg() {
184
- return d.ArgErr()
185
- }
186
- chooseStr := d.Val()
187
- choose, err := strconv.Atoi(chooseStr)
188
- if err != nil {
189
- return d.Errf("invalid choice value '%s': %v", chooseStr, err)
190
- }
191
- r.Choose = choose
181
+ d.Next() // consume policy name
182
+
183
+ if !d.NextArg() {
184
+ return d.ArgErr()
185
}
186
+ chooseStr := d.Val()
187
+ choose, err := strconv.Atoi(chooseStr)
188
+ if err != nil {
189
+ return d.Errf("invalid choice value '%s': %v", chooseStr, err)
190
+ }
191
+ r.Choose = choose
192
return nil
193
}
194
@@ -280,10 +279,9 @@ func (LeastConnSelection) Select(pool UpstreamPool, _ *http.Request, _ http.Resp
279
280
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
281
func (r *LeastConnSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
283
- for d.Next() {
284
- if d.NextArg() {
285
- return d.ArgErr()
286
- }
282
+ d.Next() // consume policy name
283
+ if d.NextArg() {
284
+ return d.ArgErr()
285
}
286
return nil
287
}
@@ -320,10 +318,9 @@ func (r *RoundRobinSelection) Select(pool UpstreamPool, _ *http.Request, _ http.
318
319
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
320
func (r *RoundRobinSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
323
- for d.Next() {
324
- if d.NextArg() {
325
- return d.ArgErr()
326
- }
321
+ d.Next() // consume policy name
322
+ if d.NextArg() {
323
+ return d.ArgErr()
324
}
325
return nil
326
}
@@ -352,10 +349,9 @@ func (FirstSelection) Select(pool UpstreamPool, _ *http.Request, _ http.Response
349
350
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
351
func (r *FirstSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
355
- for d.Next() {
356
- if d.NextArg() {
357
- return d.ArgErr()
358
- }
352
+ d.Next() // consume policy name
353
+ if d.NextArg() {
354
+ return d.ArgErr()
355
}
356
return nil
357
}
@@ -383,10 +379,9 @@ func (IPHashSelection) Select(pool UpstreamPool, req *http.Request, _ http.Respo
379
380
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
381
func (r *IPHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
386
- for d.Next() {
387
- if d.NextArg() {
388
- return d.ArgErr()
389
- }
382
+ d.Next() // consume policy name
383
+ if d.NextArg() {
384
+ return d.ArgErr()
385
}
386
return nil
387
}
@@ -416,10 +411,9 @@ func (ClientIPHashSelection) Select(pool UpstreamPool, req *http.Request, _ http
411
412
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
413
func (r *ClientIPHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
419
- for d.Next() {
420
- if d.NextArg() {
421
- return d.ArgErr()
422
- }
414
+ d.Next() // consume policy name
415
+ if d.NextArg() {
416
+ return d.ArgErr()
417
}
418
return nil
419
}
@@ -443,10 +437,9 @@ func (URIHashSelection) Select(pool UpstreamPool, req *http.Request, _ http.Resp
437
438
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
439
func (r *URIHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
446
- for d.Next() {
447
- if d.NextArg() {
448
- return d.ArgErr()
449
- }
440
+ d.Next() // consume policy name
441
+ if d.NextArg() {
442
+ return d.ArgErr()
443
}
444
return nil
445
}
@@ -504,13 +497,14 @@ func (s QueryHashSelection) Select(pool UpstreamPool, req *http.Request, _ http.
497
498
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
499
func (s *QueryHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
507
- for d.Next() {
508
- if !d.NextArg() {
509
- return d.ArgErr()
510
- }
511
- s.Key = d.Val()
500
+ d.Next() // consume policy name
501
+
502
+ if !d.NextArg() {
503
+ return d.ArgErr()
504
}
513
- for nesting := d.Nesting(); d.NextBlock(nesting); {
505
+ s.Key = d.Val()
506
+
507
+ for d.NextBlock(0) {
508
switch d.Val() {
509
case "fallback":
510
if !d.NextArg() {
@@ -583,13 +577,14 @@ func (s HeaderHashSelection) Select(pool UpstreamPool, req *http.Request, _ http
577
578
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
579
func (s *HeaderHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
586
- for d.Next() {
587
- if !d.NextArg() {
588
- return d.ArgErr()
589
- }
590
- s.Field = d.Val()
580
+ d.Next() // consume policy name
581
+
582
+ if !d.NextArg() {
583
+ return d.ArgErr()
584
}
592
- for nesting := d.Nesting(); d.NextBlock(nesting); {
585
+ s.Field = d.Val()
586
+
587
+ for d.NextBlock(0) {
588
switch d.Val() {
589
case "fallback":
590
if !d.NextArg() {
@@ -708,7 +703,7 @@ func (s *CookieHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
703
default:
704
return d.ArgErr()
705
}
711
- for nesting := d.Nesting(); d.NextBlock(nesting); {
706
+ for d.NextBlock(0) {
707
switch d.Val() {
708
case "fallback":
709
if !d.NextArg() {
modules/caddyhttp/rewrite/caddyfile.go
+71
-88
@@ -39,10 +39,7 @@ func init() {
39
// Only URI components which are given in <to> will be set in the resulting URI.
40
// See the docs for the rewrite handler for more information.
41
func parseCaddyfileRewrite(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
42
- // consume directive name
43
- if !h.NextArg() {
44
- return nil, h.ArgErr()
45
- }
42
+ h.Next() // consume directive name
43
44
// count the tokens to determine what to do
45
argsCount := h.CountRemainingArgs()
@@ -66,26 +63,9 @@ func parseCaddyfileRewrite(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue,
63
if err != nil {
64
return nil, err
65
}
66
+ h.Next() // consume directive name again, matcher parsing does a reset
67
+ h.Next() // advance to the rewrite URI
68
70
- // consume directive name, again, because extracting matcher does a reset
71
- if !h.NextArg() {
72
- return nil, h.ArgErr()
73
- }
74
- // advance to the rewrite URI
75
- if !h.NextArg() {
76
- return nil, h.ArgErr()
77
- }
78
-
79
- var rewr Rewrite
80
- for h.Next() {
81
- if !h.NextArg() {
82
- return nil, h.ArgErr()
83
- }
84
- rewr.URI = h.Val()
85
- if h.NextArg() {
86
- return nil, h.ArgErr()
87
- }
88
- }
69
return h.NewRoute(userMatcherSet, Rewrite{URI: h.Val()}), nil
70
}
71
@@ -93,17 +73,14 @@ func parseCaddyfileRewrite(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue,
73
//
74
// method [<matcher>] <method>
75
func parseCaddyfileMethod(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
96
- var rewr Rewrite
97
- for h.Next() {
98
- if !h.NextArg() {
99
- return nil, h.ArgErr()
100
- }
101
- rewr.Method = h.Val()
102
- if h.NextArg() {
103
- return nil, h.ArgErr()
104
- }
76
+ h.Next() // consume directive name
77
+ if !h.NextArg() {
78
+ return nil, h.ArgErr()
79
}
106
- return rewr, nil
80
+ if h.NextArg() {
81
+ return nil, h.ArgErr()
82
+ }
83
+ return Rewrite{Method: h.Val()}, nil
84
}
85
86
// parseCaddyfileURI sets up a handler for manipulating (but not "rewriting") the
@@ -118,65 +95,71 @@ func parseCaddyfileMethod(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler,
95
// path_regexp is used, then regular expression replacements will be performed
96
// on the path portion of the URI (and a limit cannot be set).
97
func parseCaddyfileURI(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
98
+ h.Next() // consume directive name
99
+
100
+ args := h.RemainingArgs()
101
+ if len(args) < 2 {
102
+ return nil, h.ArgErr()
103
+ }
104
+
105
var rewr Rewrite
122
- for h.Next() {
123
- args := h.RemainingArgs()
124
- if len(args) < 2 {
106
+
107
+ switch args[0] {
108
+ case "strip_prefix":
109
+ if len(args) > 2 {
110
return nil, h.ArgErr()
111
}
127
- switch args[0] {
128
- case "strip_prefix":
129
- if len(args) > 2 {
130
- return nil, h.ArgErr()
131
- }
132
- rewr.StripPathPrefix = args[1]
133
- if !strings.HasPrefix(rewr.StripPathPrefix, "/") {
134
- rewr.StripPathPrefix = "/" + rewr.StripPathPrefix
135
- }
136
- case "strip_suffix":
137
- if len(args) > 2 {
138
- return nil, h.ArgErr()
139
- }
140
- rewr.StripPathSuffix = args[1]
141
- case "replace":
142
- var find, replace, lim string
143
- switch len(args) {
144
- case 4:
145
- lim = args[3]
146
- fallthrough
147
- case 3:
148
- find = args[1]
149
- replace = args[2]
150
- default:
151
- return nil, h.ArgErr()
152
- }
112
+ rewr.StripPathPrefix = args[1]
113
+ if !strings.HasPrefix(rewr.StripPathPrefix, "/") {
114
+ rewr.StripPathPrefix = "/" + rewr.StripPathPrefix
115
+ }
116
154
- var limInt int
155
- if lim != "" {
156
- var err error
157
- limInt, err = strconv.Atoi(lim)
158
- if err != nil {
159
- return nil, h.Errf("limit must be an integer; invalid: %v", err)
160
- }
161
- }
117
+ case "strip_suffix":
118
+ if len(args) > 2 {
119
+ return nil, h.ArgErr()
120
+ }
121
+ rewr.StripPathSuffix = args[1]
122
+
123
+ case "replace":
124
+ var find, replace, lim string
125
+ switch len(args) {
126
+ case 4:
127
+ lim = args[3]
128
+ fallthrough
129
+ case 3:
130
+ find = args[1]
131
+ replace = args[2]
132
+ default:
133
+ return nil, h.ArgErr()
134
+ }
135
163
- rewr.URISubstring = append(rewr.URISubstring, substrReplacer{
164
- Find: find,
165
- Replace: replace,
166
- Limit: limInt,
167
- })
168
- case "path_regexp":
169
- if len(args) != 3 {
170
- return nil, h.ArgErr()
136
+ var limInt int
137
+ if lim != "" {
138
+ var err error
139
+ limInt, err = strconv.Atoi(lim)
140
+ if err != nil {
141
+ return nil, h.Errf("limit must be an integer; invalid: %v", err)
142
}
172
- find, replace := args[1], args[2]
173
- rewr.PathRegexp = append(rewr.PathRegexp, ®exReplacer{
174
- Find: find,
175
- Replace: replace,
176
- })
177
- default:
178
- return nil, h.Errf("unrecognized URI manipulation '%s'", args[0])
143
}
144
+
145
+ rewr.URISubstring = append(rewr.URISubstring, substrReplacer{
146
+ Find: find,
147
+ Replace: replace,
148
+ Limit: limInt,
149
+ })
150
+
151
+ case "path_regexp":
152
+ if len(args) != 3 {
153
+ return nil, h.ArgErr()
154
+ }
155
+ find, replace := args[1], args[2]
156
+ rewr.PathRegexp = append(rewr.PathRegexp, ®exReplacer{
157
+ Find: find,
158
+ Replace: replace,
159
+ })
160
+
161
+ default:
162
+ return nil, h.Errf("unrecognized URI manipulation '%s'", args[0])
163
}
164
return rewr, nil
165
}
@@ -190,9 +173,9 @@ func parseCaddyfileURI(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, err
173
// Only path matchers (with a `/` prefix) are supported as this is a shortcut
174
// for the handle directive with a strip_prefix rewrite.
175
func parseCaddyfileHandlePath(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
193
- if !h.Next() {
194
- return nil, h.ArgErr()
195
- }
176
+ h.Next() // consume directive name
177
+
178
+ // there must be a path matcher
179
if !h.NextArg() {
180
return nil, h.ArgErr()
181
}
modules/caddyhttp/staticerror.go
+25
-26
@@ -60,36 +60,35 @@ func (StaticError) CaddyModule() caddy.ModuleInfo {
60
// If there is just one argument (other than the matcher), it is considered
61
// to be a status code if it's a valid positive integer of 3 digits.
62
func (e *StaticError) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
63
- for d.Next() {
64
- args := d.RemainingArgs()
65
- switch len(args) {
66
- case 1:
67
- if len(args[0]) == 3 {
68
- if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
69
- e.StatusCode = WeakString(args[0])
70
- break
71
- }
63
+ d.Next() // consume directive name
64
+ args := d.RemainingArgs()
65
+ switch len(args) {
66
+ case 1:
67
+ if len(args[0]) == 3 {
68
+ if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
69
+ e.StatusCode = WeakString(args[0])
70
+ break
71
}
73
- e.Error = args[0]
74
- case 2:
75
- e.Error = args[0]
76
- e.StatusCode = WeakString(args[1])
77
- default:
78
- return d.ArgErr()
72
}
73
+ e.Error = args[0]
74
+ case 2:
75
+ e.Error = args[0]
76
+ e.StatusCode = WeakString(args[1])
77
+ default:
78
+ return d.ArgErr()
79
+ }
80
81
- for d.NextBlock(0) {
82
- switch d.Val() {
83
- case "message":
84
- if e.Error != "" {
85
- return d.Err("message already specified")
86
- }
87
- if !d.AllArgs(&e.Error) {
88
- return d.ArgErr()
89
- }
90
- default:
91
- return d.Errf("unrecognized subdirective '%s'", d.Val())
81
+ for d.NextBlock(0) {
82
+ switch d.Val() {
83
+ case "message":
84
+ if e.Error != "" {
85
+ return d.Err("message already specified")
86
}
87
+ if !d.AllArgs(&e.Error) {
88
+ return d.ArgErr()
89
+ }
90
+ default:
91
+ return d.Errf("unrecognized subdirective '%s'", d.Val())
92
}
93
}
94
return nil
modules/caddyhttp/staticresp.go
+30
-31
@@ -138,41 +138,40 @@ func (StaticResponse) CaddyModule() caddy.ModuleInfo {
138
// If there is just one argument (other than the matcher), it is considered
139
// to be a status code if it's a valid positive integer of 3 digits.
140
func (s *StaticResponse) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
141
- for d.Next() {
142
- args := d.RemainingArgs()
143
- switch len(args) {
144
- case 1:
145
- if len(args[0]) == 3 {
146
- if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
147
- s.StatusCode = WeakString(args[0])
148
- break
149
- }
141
+ d.Next() // consume directive name
142
+ args := d.RemainingArgs()
143
+ switch len(args) {
144
+ case 1:
145
+ if len(args[0]) == 3 {
146
+ if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
147
+ s.StatusCode = WeakString(args[0])
148
+ break
149
}
151
- s.Body = args[0]
152
- case 2:
153
- s.Body = args[0]
154
- s.StatusCode = WeakString(args[1])
155
- default:
156
- return d.ArgErr()
150
}
151
+ s.Body = args[0]
152
+ case 2:
153
+ s.Body = args[0]
154
+ s.StatusCode = WeakString(args[1])
155
+ default:
156
+ return d.ArgErr()
157
+ }
158
159
- for d.NextBlock(0) {
160
- switch d.Val() {
161
- case "body":
162
- if s.Body != "" {
163
- return d.Err("body already specified")
164
- }
165
- if !d.AllArgs(&s.Body) {
166
- return d.ArgErr()
167
- }
168
- case "close":
169
- if s.Close {
170
- return d.Err("close already specified")
171
- }
172
- s.Close = true
173
- default:
174
- return d.Errf("unrecognized subdirective '%s'", d.Val())
159
+ for d.NextBlock(0) {
160
+ switch d.Val() {
161
+ case "body":
162
+ if s.Body != "" {
163
+ return d.Err("body already specified")
164
+ }
165
+ if !d.AllArgs(&s.Body) {
166
+ return d.ArgErr()
167
}
168
+ case "close":
169
+ if s.Close {
170
+ return d.Err("close already specified")
171
+ }
172
+ s.Close = true
173
+ default:
174
+ return d.Errf("unrecognized subdirective '%s'", d.Val())
175
}
176
}
177
return nil
modules/caddyhttp/templates/caddyfile.go
+36
-37
@@ -34,47 +34,46 @@ func init() {
34
// root <path>
35
// }
36
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
37
+ h.Next() // consume directive name
38
t := new(Templates)
38
- for h.Next() {
39
- for h.NextBlock(0) {
40
- switch h.Val() {
41
- case "mime":
42
- t.MIMETypes = h.RemainingArgs()
43
- if len(t.MIMETypes) == 0 {
44
- return nil, h.ArgErr()
45
- }
46
- case "between":
47
- t.Delimiters = h.RemainingArgs()
48
- if len(t.Delimiters) != 2 {
49
- return nil, h.ArgErr()
50
- }
51
- case "root":
52
- if !h.Args(&t.FileRoot) {
53
- return nil, h.ArgErr()
54
- }
55
- case "extensions":
56
- if h.NextArg() {
57
- return nil, h.ArgErr()
39
+ for h.NextBlock(0) {
40
+ switch h.Val() {
41
+ case "mime":
42
+ t.MIMETypes = h.RemainingArgs()
43
+ if len(t.MIMETypes) == 0 {
44
+ return nil, h.ArgErr()
45
+ }
46
+ case "between":
47
+ t.Delimiters = h.RemainingArgs()
48
+ if len(t.Delimiters) != 2 {
49
+ return nil, h.ArgErr()
50
+ }
51
+ case "root":
52
+ if !h.Args(&t.FileRoot) {
53
+ return nil, h.ArgErr()
54
+ }
55
+ case "extensions":
56
+ if h.NextArg() {
57
+ return nil, h.ArgErr()
58
+ }
59
+ if t.ExtensionsRaw != nil {
60
+ return nil, h.Err("extensions already specified")
61
+ }
62
+ for nesting := h.Nesting(); h.NextBlock(nesting); {
63
+ extensionModuleName := h.Val()
64
+ modID := "http.handlers.templates.functions." + extensionModuleName
65
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
66
+ if err != nil {
67
+ return nil, err
68
}
59
- if t.ExtensionsRaw != nil {
60
- return nil, h.Err("extensions already specified")
69
+ cf, ok := unm.(CustomFunctions)
70
+ if !ok {
71
+ return nil, h.Errf("module %s (%T) does not provide template functions", modID, unm)
72
}
62
- for nesting := h.Nesting(); h.NextBlock(nesting); {
63
- extensionModuleName := h.Val()
64
- modID := "http.handlers.templates.functions." + extensionModuleName
65
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
66
- if err != nil {
67
- return nil, err
68
- }
69
- cf, ok := unm.(CustomFunctions)
70
- if !ok {
71
- return nil, h.Errf("module %s (%T) does not provide template functions", modID, unm)
72
- }
73
- if t.ExtensionsRaw == nil {
74
- t.ExtensionsRaw = make(caddy.ModuleMap)
75
- }
76
- t.ExtensionsRaw[extensionModuleName] = caddyconfig.JSON(cf, nil)
73
+ if t.ExtensionsRaw == nil {
74
+ t.ExtensionsRaw = make(caddy.ModuleMap)
75
}
76
+ t.ExtensionsRaw[extensionModuleName] = caddyconfig.JSON(cf, nil)
77
}
78
}
79
}
modules/caddyhttp/tracing/module.go
+10
-12
@@ -88,20 +88,18 @@ func (ot *Tracing) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
88
"span": &ot.SpanName,
89
}
90
91
- for d.Next() {
92
- args := d.RemainingArgs()
93
- if len(args) > 0 {
94
- return d.ArgErr()
95
- }
91
+ d.Next() // consume directive name
92
+ if d.NextArg() {
93
+ return d.ArgErr()
94
+ }
95
97
- for d.NextBlock(0) {
98
- if dst, ok := paramsMap[d.Val()]; ok {
99
- if err := setParameter(d, dst); err != nil {
100
- return err
101
- }
102
- } else {
103
- return d.ArgErr()
96
+ for d.NextBlock(0) {
97
+ if dst, ok := paramsMap[d.Val()]; ok {
98
+ if err := setParameter(d, dst); err != nil {
99
+ return err
100
}
101
+ } else {
102
+ return d.ArgErr()
103
}
104
}
105
return nil
modules/caddyhttp/vars.go
+9
-7
@@ -68,6 +68,8 @@ func (m VarsMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next H
68
// ...
69
// }
70
func (m *VarsMiddleware) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
71
+ d.Next() // consume directive name
72
+
73
if *m == nil {
74
*m = make(VarsMiddleware)
75
}
@@ -94,15 +96,13 @@ func (m *VarsMiddleware) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
96
return nil
97
}
98
97
- for d.Next() {
98
- if err := nextVar(true); err != nil {
99
+ if err := nextVar(true); err != nil {
100
+ return err
101
+ }
102
+ for d.NextBlock(0) {
103
+ if err := nextVar(false); err != nil {
104
return err
105
}
101
- for nesting := d.Nesting(); d.NextBlock(nesting); {
102
- if err := nextVar(false); err != nil {
103
- return err
104
- }
105
- }
106
}
107
108
return nil
@@ -135,6 +135,7 @@ func (m *VarsMatcher) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
135
if *m == nil {
136
*m = make(map[string][]string)
137
}
138
+ // iterate to merge multiple matchers into one
139
for d.Next() {
140
var field string
141
if !d.Args(&field) {
@@ -216,6 +217,7 @@ func (m *MatchVarsRE) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
217
if *m == nil {
218
*m = make(map[string]*MatchRegexp)
219
}
220
+ // iterate to merge multiple matchers into one
221
for d.Next() {
222
var first, second, third string
223
if !d.Args(&first, &second) {
modules/caddypki/acmeserver/caddyfile.go
+38
-39
@@ -34,53 +34,52 @@ func init() {
34
// resolvers <addresses...>
35
// }
36
func parseACMEServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
37
- if !h.Next() {
38
- return nil, h.ArgErr()
39
- }
40
-
37
+ h.Next() // consume directive name
38
matcherSet, err := h.ExtractMatcherSet()
39
if err != nil {
40
return nil, err
41
}
42
+ h.Next() // consume the directive name again (matcher parsing resets)
43
+
44
+ // no inline args allowed
45
+ if h.NextArg() {
46
+ return nil, h.ArgErr()
47
+ }
48
49
var acmeServer Handler
50
var ca *caddypki.CA
51
49
- for h.Next() {
50
- if h.NextArg() {
51
- return nil, h.ArgErr()
52
- }
53
- for h.NextBlock(0) {
54
- switch h.Val() {
55
- case "ca":
56
- if !h.AllArgs(&acmeServer.CA) {
57
- return nil, h.ArgErr()
58
- }
59
- if ca == nil {
60
- ca = new(caddypki.CA)
61
- }
62
- ca.ID = acmeServer.CA
63
- case "lifetime":
64
- if !h.NextArg() {
65
- return nil, h.ArgErr()
66
- }
67
-
68
- dur, err := caddy.ParseDuration(h.Val())
69
- if err != nil {
70
- return nil, err
71
- }
72
-
73
- if d := time.Duration(ca.IntermediateLifetime); d > 0 && dur > d {
74
- return nil, h.Errf("certificate lifetime (%s) exceeds intermediate certificate lifetime (%s)", dur, d)
75
- }
76
-
77
- acmeServer.Lifetime = caddy.Duration(dur)
78
-
79
- case "resolvers":
80
- acmeServer.Resolvers = h.RemainingArgs()
81
- if len(acmeServer.Resolvers) == 0 {
82
- return nil, h.Errf("must specify at least one resolver address")
83
- }
52
+ for h.NextBlock(0) {
53
+ switch h.Val() {
54
+ case "ca":
55
+ if !h.AllArgs(&acmeServer.CA) {
56
+ return nil, h.ArgErr()
57
+ }
58
+ if ca == nil {
59
+ ca = new(caddypki.CA)
60
+ }
61
+ ca.ID = acmeServer.CA
62
+
63
+ case "lifetime":
64
+ if !h.NextArg() {
65
+ return nil, h.ArgErr()
66
+ }
67
+
68
+ dur, err := caddy.ParseDuration(h.Val())
69
+ if err != nil {
70
+ return nil, err
71
+ }
72
+
73
+ if d := time.Duration(ca.IntermediateLifetime); d > 0 && dur > d {
74
+ return nil, h.Errf("certificate lifetime (%s) exceeds intermediate certificate lifetime (%s)", dur, d)
75
+ }
76
+
77
+ acmeServer.Lifetime = caddy.Duration(dur)
78
+
79
+ case "resolvers":
80
+ acmeServer.Resolvers = h.RemainingArgs()
81
+ if len(acmeServer.Resolvers) == 0 {
82
+ return nil, h.Errf("must specify at least one resolver address")
83
}
84
}
85
}
modules/caddytls/acmeissuer.go
+192
-191
@@ -277,218 +277,219 @@ func (iss *ACMEIssuer) GetACMEIssuer() *ACMEIssuer { return iss }
277
// }
278
// }
279
func (iss *ACMEIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
280
- for d.Next() {
280
+ d.Next() // consume issuer name
281
+
282
+ if d.NextArg() {
283
+ iss.CA = d.Val()
284
if d.NextArg() {
282
- iss.CA = d.Val()
283
- if d.NextArg() {
284
- return d.ArgErr()
285
- }
285
+ return d.ArgErr()
286
}
287
- for nesting := d.Nesting(); d.NextBlock(nesting); {
288
- switch d.Val() {
289
- case "dir":
290
- if iss.CA != "" {
291
- return d.Errf("directory is already specified: %s", iss.CA)
292
- }
293
- if !d.AllArgs(&iss.CA) {
294
- return d.ArgErr()
295
- }
296
-
297
- case "test_dir":
298
- if !d.AllArgs(&iss.TestCA) {
299
- return d.ArgErr()
300
- }
287
+ }
288
302
- case "email":
303
- if !d.AllArgs(&iss.Email) {
304
- return d.ArgErr()
305
- }
289
+ for d.NextBlock(0) {
290
+ switch d.Val() {
291
+ case "dir":
292
+ if iss.CA != "" {
293
+ return d.Errf("directory is already specified: %s", iss.CA)
294
+ }
295
+ if !d.AllArgs(&iss.CA) {
296
+ return d.ArgErr()
297
+ }
298
307
- case "timeout":
308
- var timeoutStr string
309
- if !d.AllArgs(&timeoutStr) {
310
- return d.ArgErr()
311
- }
312
- timeout, err := caddy.ParseDuration(timeoutStr)
313
- if err != nil {
314
- return d.Errf("invalid timeout duration %s: %v", timeoutStr, err)
315
- }
316
- iss.ACMETimeout = caddy.Duration(timeout)
299
+ case "test_dir":
300
+ if !d.AllArgs(&iss.TestCA) {
301
+ return d.ArgErr()
302
+ }
303
318
- case "disable_http_challenge":
319
- if d.NextArg() {
320
- return d.ArgErr()
321
- }
322
- if iss.Challenges == nil {
323
- iss.Challenges = new(ChallengesConfig)
324
- }
325
- if iss.Challenges.HTTP == nil {
326
- iss.Challenges.HTTP = new(HTTPChallengeConfig)
327
- }
328
- iss.Challenges.HTTP.Disabled = true
304
+ case "email":
305
+ if !d.AllArgs(&iss.Email) {
306
+ return d.ArgErr()
307
+ }
308
330
- case "disable_tlsalpn_challenge":
331
- if d.NextArg() {
332
- return d.ArgErr()
333
- }
334
- if iss.Challenges == nil {
335
- iss.Challenges = new(ChallengesConfig)
336
- }
337
- if iss.Challenges.TLSALPN == nil {
338
- iss.Challenges.TLSALPN = new(TLSALPNChallengeConfig)
339
- }
340
- iss.Challenges.TLSALPN.Disabled = true
309
+ case "timeout":
310
+ var timeoutStr string
311
+ if !d.AllArgs(&timeoutStr) {
312
+ return d.ArgErr()
313
+ }
314
+ timeout, err := caddy.ParseDuration(timeoutStr)
315
+ if err != nil {
316
+ return d.Errf("invalid timeout duration %s: %v", timeoutStr, err)
317
+ }
318
+ iss.ACMETimeout = caddy.Duration(timeout)
319
342
- case "alt_http_port":
343
- if !d.NextArg() {
344
- return d.ArgErr()
345
- }
346
- port, err := strconv.Atoi(d.Val())
347
- if err != nil {
348
- return d.Errf("invalid port %s: %v", d.Val(), err)
349
- }
350
- if iss.Challenges == nil {
351
- iss.Challenges = new(ChallengesConfig)
352
- }
353
- if iss.Challenges.HTTP == nil {
354
- iss.Challenges.HTTP = new(HTTPChallengeConfig)
355
- }
356
- iss.Challenges.HTTP.AlternatePort = port
320
+ case "disable_http_challenge":
321
+ if d.NextArg() {
322
+ return d.ArgErr()
323
+ }
324
+ if iss.Challenges == nil {
325
+ iss.Challenges = new(ChallengesConfig)
326
+ }
327
+ if iss.Challenges.HTTP == nil {
328
+ iss.Challenges.HTTP = new(HTTPChallengeConfig)
329
+ }
330
+ iss.Challenges.HTTP.Disabled = true
331
358
- case "alt_tlsalpn_port":
359
- if !d.NextArg() {
360
- return d.ArgErr()
361
- }
362
- port, err := strconv.Atoi(d.Val())
363
- if err != nil {
364
- return d.Errf("invalid port %s: %v", d.Val(), err)
365
- }
366
- if iss.Challenges == nil {
367
- iss.Challenges = new(ChallengesConfig)
368
- }
369
- if iss.Challenges.TLSALPN == nil {
370
- iss.Challenges.TLSALPN = new(TLSALPNChallengeConfig)
371
- }
372
- iss.Challenges.TLSALPN.AlternatePort = port
332
+ case "disable_tlsalpn_challenge":
333
+ if d.NextArg() {
334
+ return d.ArgErr()
335
+ }
336
+ if iss.Challenges == nil {
337
+ iss.Challenges = new(ChallengesConfig)
338
+ }
339
+ if iss.Challenges.TLSALPN == nil {
340
+ iss.Challenges.TLSALPN = new(TLSALPNChallengeConfig)
341
+ }
342
+ iss.Challenges.TLSALPN.Disabled = true
343
374
- case "eab":
375
- iss.ExternalAccount = new(acme.EAB)
376
- if !d.AllArgs(&iss.ExternalAccount.KeyID, &iss.ExternalAccount.MACKey) {
377
- return d.ArgErr()
378
- }
344
+ case "alt_http_port":
345
+ if !d.NextArg() {
346
+ return d.ArgErr()
347
+ }
348
+ port, err := strconv.Atoi(d.Val())
349
+ if err != nil {
350
+ return d.Errf("invalid port %s: %v", d.Val(), err)
351
+ }
352
+ if iss.Challenges == nil {
353
+ iss.Challenges = new(ChallengesConfig)
354
+ }
355
+ if iss.Challenges.HTTP == nil {
356
+ iss.Challenges.HTTP = new(HTTPChallengeConfig)
357
+ }
358
+ iss.Challenges.HTTP.AlternatePort = port
359
380
- case "trusted_roots":
381
- iss.TrustedRootsPEMFiles = d.RemainingArgs()
360
+ case "alt_tlsalpn_port":
361
+ if !d.NextArg() {
362
+ return d.ArgErr()
363
+ }
364
+ port, err := strconv.Atoi(d.Val())
365
+ if err != nil {
366
+ return d.Errf("invalid port %s: %v", d.Val(), err)
367
+ }
368
+ if iss.Challenges == nil {
369
+ iss.Challenges = new(ChallengesConfig)
370
+ }
371
+ if iss.Challenges.TLSALPN == nil {
372
+ iss.Challenges.TLSALPN = new(TLSALPNChallengeConfig)
373
+ }
374
+ iss.Challenges.TLSALPN.AlternatePort = port
375
383
- case "dns":
384
- if !d.NextArg() {
385
- return d.ArgErr()
386
- }
387
- provName := d.Val()
388
- if iss.Challenges == nil {
389
- iss.Challenges = new(ChallengesConfig)
390
- }
391
- if iss.Challenges.DNS == nil {
392
- iss.Challenges.DNS = new(DNSChallengeConfig)
393
- }
394
- unm, err := caddyfile.UnmarshalModule(d, "dns.providers."+provName)
395
- if err != nil {
396
- return err
397
- }
398
- iss.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, nil)
376
+ case "eab":
377
+ iss.ExternalAccount = new(acme.EAB)
378
+ if !d.AllArgs(&iss.ExternalAccount.KeyID, &iss.ExternalAccount.MACKey) {
379
+ return d.ArgErr()
380
+ }
381
400
- case "propagation_delay":
401
- if !d.NextArg() {
402
- return d.ArgErr()
403
- }
404
- delayStr := d.Val()
405
- delay, err := caddy.ParseDuration(delayStr)
406
- if err != nil {
407
- return d.Errf("invalid propagation_delay duration %s: %v", delayStr, err)
408
- }
409
- if iss.Challenges == nil {
410
- iss.Challenges = new(ChallengesConfig)
411
- }
412
- if iss.Challenges.DNS == nil {
413
- iss.Challenges.DNS = new(DNSChallengeConfig)
414
- }
415
- iss.Challenges.DNS.PropagationDelay = caddy.Duration(delay)
382
+ case "trusted_roots":
383
+ iss.TrustedRootsPEMFiles = d.RemainingArgs()
384
417
- case "propagation_timeout":
418
- if !d.NextArg() {
419
- return d.ArgErr()
420
- }
421
- timeoutStr := d.Val()
422
- var timeout time.Duration
423
- if timeoutStr == "-1" {
424
- timeout = time.Duration(-1)
425
- } else {
426
- var err error
427
- timeout, err = caddy.ParseDuration(timeoutStr)
428
- if err != nil {
429
- return d.Errf("invalid propagation_timeout duration %s: %v", timeoutStr, err)
430
- }
431
- }
432
- if iss.Challenges == nil {
433
- iss.Challenges = new(ChallengesConfig)
434
- }
435
- if iss.Challenges.DNS == nil {
436
- iss.Challenges.DNS = new(DNSChallengeConfig)
437
- }
438
- iss.Challenges.DNS.PropagationTimeout = caddy.Duration(timeout)
385
+ case "dns":
386
+ if !d.NextArg() {
387
+ return d.ArgErr()
388
+ }
389
+ provName := d.Val()
390
+ if iss.Challenges == nil {
391
+ iss.Challenges = new(ChallengesConfig)
392
+ }
393
+ if iss.Challenges.DNS == nil {
394
+ iss.Challenges.DNS = new(DNSChallengeConfig)
395
+ }
396
+ unm, err := caddyfile.UnmarshalModule(d, "dns.providers."+provName)
397
+ if err != nil {
398
+ return err
399
+ }
400
+ iss.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, nil)
401
440
- case "resolvers":
441
- if iss.Challenges == nil {
442
- iss.Challenges = new(ChallengesConfig)
443
- }
444
- if iss.Challenges.DNS == nil {
445
- iss.Challenges.DNS = new(DNSChallengeConfig)
446
- }
447
- iss.Challenges.DNS.Resolvers = d.RemainingArgs()
448
- if len(iss.Challenges.DNS.Resolvers) == 0 {
449
- return d.ArgErr()
450
- }
402
+ case "propagation_delay":
403
+ if !d.NextArg() {
404
+ return d.ArgErr()
405
+ }
406
+ delayStr := d.Val()
407
+ delay, err := caddy.ParseDuration(delayStr)
408
+ if err != nil {
409
+ return d.Errf("invalid propagation_delay duration %s: %v", delayStr, err)
410
+ }
411
+ if iss.Challenges == nil {
412
+ iss.Challenges = new(ChallengesConfig)
413
+ }
414
+ if iss.Challenges.DNS == nil {
415
+ iss.Challenges.DNS = new(DNSChallengeConfig)
416
+ }
417
+ iss.Challenges.DNS.PropagationDelay = caddy.Duration(delay)
418
452
- case "dns_ttl":
453
- if !d.NextArg() {
454
- return d.ArgErr()
455
- }
456
- ttlStr := d.Val()
457
- ttl, err := caddy.ParseDuration(ttlStr)
419
+ case "propagation_timeout":
420
+ if !d.NextArg() {
421
+ return d.ArgErr()
422
+ }
423
+ timeoutStr := d.Val()
424
+ var timeout time.Duration
425
+ if timeoutStr == "-1" {
426
+ timeout = time.Duration(-1)
427
+ } else {
428
+ var err error
429
+ timeout, err = caddy.ParseDuration(timeoutStr)
430
if err != nil {
459
- return d.Errf("invalid dns_ttl duration %s: %v", ttlStr, err)
460
- }
461
- if iss.Challenges == nil {
462
- iss.Challenges = new(ChallengesConfig)
431
+ return d.Errf("invalid propagation_timeout duration %s: %v", timeoutStr, err)
432
}
464
- if iss.Challenges.DNS == nil {
465
- iss.Challenges.DNS = new(DNSChallengeConfig)
466
- }
467
- iss.Challenges.DNS.TTL = caddy.Duration(ttl)
433
+ }
434
+ if iss.Challenges == nil {
435
+ iss.Challenges = new(ChallengesConfig)
436
+ }
437
+ if iss.Challenges.DNS == nil {
438
+ iss.Challenges.DNS = new(DNSChallengeConfig)
439
+ }
440
+ iss.Challenges.DNS.PropagationTimeout = caddy.Duration(timeout)
441
469
- case "dns_challenge_override_domain":
470
- arg := d.RemainingArgs()
471
- if len(arg) != 1 {
472
- return d.ArgErr()
473
- }
474
- if iss.Challenges == nil {
475
- iss.Challenges = new(ChallengesConfig)
476
- }
477
- if iss.Challenges.DNS == nil {
478
- iss.Challenges.DNS = new(DNSChallengeConfig)
479
- }
480
- iss.Challenges.DNS.OverrideDomain = arg[0]
442
+ case "resolvers":
443
+ if iss.Challenges == nil {
444
+ iss.Challenges = new(ChallengesConfig)
445
+ }
446
+ if iss.Challenges.DNS == nil {
447
+ iss.Challenges.DNS = new(DNSChallengeConfig)
448
+ }
449
+ iss.Challenges.DNS.Resolvers = d.RemainingArgs()
450
+ if len(iss.Challenges.DNS.Resolvers) == 0 {
451
+ return d.ArgErr()
452
+ }
453
482
- case "preferred_chains":
483
- chainPref, err := ParseCaddyfilePreferredChainsOptions(d)
484
- if err != nil {
485
- return err
486
- }
487
- iss.PreferredChains = chainPref
454
+ case "dns_ttl":
455
+ if !d.NextArg() {
456
+ return d.ArgErr()
457
+ }
458
+ ttlStr := d.Val()
459
+ ttl, err := caddy.ParseDuration(ttlStr)
460
+ if err != nil {
461
+ return d.Errf("invalid dns_ttl duration %s: %v", ttlStr, err)
462
+ }
463
+ if iss.Challenges == nil {
464
+ iss.Challenges = new(ChallengesConfig)
465
+ }
466
+ if iss.Challenges.DNS == nil {
467
+ iss.Challenges.DNS = new(DNSChallengeConfig)
468
+ }
469
+ iss.Challenges.DNS.TTL = caddy.Duration(ttl)
470
489
- default:
490
- return d.Errf("unrecognized ACME issuer property: %s", d.Val())
471
+ case "dns_challenge_override_domain":
472
+ arg := d.RemainingArgs()
473
+ if len(arg) != 1 {
474
+ return d.ArgErr()
475
}
476
+ if iss.Challenges == nil {
477
+ iss.Challenges = new(ChallengesConfig)
478
+ }
479
+ if iss.Challenges.DNS == nil {
480
+ iss.Challenges.DNS = new(DNSChallengeConfig)
481
+ }
482
+ iss.Challenges.DNS.OverrideDomain = arg[0]
483
+
484
+ case "preferred_chains":
485
+ chainPref, err := ParseCaddyfilePreferredChainsOptions(d)
486
+ if err != nil {
487
+ return err
488
+ }
489
+ iss.PreferredChains = chainPref
490
+
491
+ default:
492
+ return d.Errf("unrecognized ACME issuer property: %s", d.Val())
493
}
494
}
495
return nil
modules/caddytls/certmanagers.go
+15
-15
@@ -72,10 +72,9 @@ func (ts Tailscale) canHazCertificate(ctx context.Context, hello *tls.ClientHell
72
//
73
// ... tailscale
74
func (Tailscale) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
75
- for d.Next() {
76
- if d.NextArg() {
77
- return d.ArgErr()
78
- }
75
+ d.Next() // consume cert manager name
76
+ if d.NextArg() {
77
+ return d.ArgErr()
78
}
79
return nil
80
}
@@ -169,17 +168,18 @@ func (hcg HTTPCertGetter) GetCertificate(ctx context.Context, hello *tls.ClientH
168
//
169
// ... http <url>
170
func (hcg *HTTPCertGetter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
172
- for d.Next() {
173
- if !d.NextArg() {
174
- return d.ArgErr()
175
- }
176
- hcg.URL = d.Val()
177
- if d.NextArg() {
178
- return d.ArgErr()
179
- }
180
- for nesting := d.Nesting(); d.NextBlock(nesting); {
181
- return d.Err("block not allowed here")
182
- }
171
+ d.Next() // consume cert manager name
172
+
173
+ if !d.NextArg() {
174
+ return d.ArgErr()
175
+ }
176
+ hcg.URL = d.Val()
177
+
178
+ if d.NextArg() {
179
+ return d.ArgErr()
180
+ }
181
+ if d.NextBlock(0) {
182
+ return d.Err("block not allowed here")
183
}
184
return nil
185
}
modules/caddytls/internalissuer.go
+22
-23
@@ -155,31 +155,30 @@ func (iss InternalIssuer) Issue(ctx context.Context, csr *x509.CertificateReques
155
// sign_with_root
156
// }
157
func (iss *InternalIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
158
- for d.Next() {
159
- for d.NextBlock(0) {
160
- switch d.Val() {
161
- case "ca":
162
- if !d.AllArgs(&iss.CA) {
163
- return d.ArgErr()
164
- }
165
-
166
- case "lifetime":
167
- if !d.NextArg() {
168
- return d.ArgErr()
169
- }
170
- dur, err := caddy.ParseDuration(d.Val())
171
- if err != nil {
172
- return err
173
- }
174
- iss.Lifetime = caddy.Duration(dur)
175
-
176
- case "sign_with_root":
177
- if d.NextArg() {
178
- return d.ArgErr()
179
- }
180
- iss.SignWithRoot = true
158
+ d.Next() // consume issuer name
159
+ for d.NextBlock(0) {
160
+ switch d.Val() {
161
+ case "ca":
162
+ if !d.AllArgs(&iss.CA) {
163
+ return d.ArgErr()
164
+ }
165
166
+ case "lifetime":
167
+ if !d.NextArg() {
168
+ return d.ArgErr()
169
+ }
170
+ dur, err := caddy.ParseDuration(d.Val())
171
+ if err != nil {
172
+ return err
173
}
174
+ iss.Lifetime = caddy.Duration(dur)
175
+
176
+ case "sign_with_root":
177
+ if d.NextArg() {
178
+ return d.ArgErr()
179
+ }
180
+ iss.SignWithRoot = true
181
+
182
}
183
}
184
return nil
modules/caddytls/zerosslissuer.go
+11
-12
@@ -208,21 +208,20 @@ func (iss *ZeroSSLIssuer) Revoke(ctx context.Context, cert certmagic.Certificate
208
//
209
// Any of the subdirectives for the ACME issuer can be used in the block.
210
func (iss *ZeroSSLIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
211
- for d.Next() {
211
+ d.Next() // consume issuer name
212
+ if d.NextArg() {
213
+ iss.APIKey = d.Val()
214
if d.NextArg() {
213
- iss.APIKey = d.Val()
214
- if d.NextArg() {
215
- return d.ArgErr()
216
- }
215
+ return d.ArgErr()
216
}
217
+ }
218
219
- if iss.ACMEIssuer == nil {
220
- iss.ACMEIssuer = new(ACMEIssuer)
221
- }
222
- err := iss.ACMEIssuer.UnmarshalCaddyfile(d.NewFromNextSegment())
223
- if err != nil {
224
- return err
225
- }
219
+ if iss.ACMEIssuer == nil {
220
+ iss.ACMEIssuer = new(ACMEIssuer)
221
+ }
222
+ err := iss.ACMEIssuer.UnmarshalCaddyfile(d.NewFromNextSegment())
223
+ if err != nil {
224
+ return err
225
}
226
return nil
227
}
modules/filestorage/filestorage.go
+1
-1
@@ -55,7 +55,7 @@ func (s *FileStorage) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
55
if d.NextArg() {
56
return d.ArgErr()
57
}
58
- for nesting := d.Nesting(); d.NextBlock(nesting); {
58
+ for d.NextBlock(0) {
59
switch d.Val() {
60
case "root":
61
if !d.NextArg() {
modules/logging/encoders.go
+15
-17
@@ -65,14 +65,13 @@ func (ce *ConsoleEncoder) Provision(_ caddy.Context) error {
65
// See the godoc on the LogEncoderConfig type for the syntax of
66
// subdirectives that are common to most/all encoders.
67
func (ce *ConsoleEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
68
- for d.Next() {
69
- if d.NextArg() {
70
- return d.ArgErr()
71
- }
72
- err := ce.LogEncoderConfig.UnmarshalCaddyfile(d)
73
- if err != nil {
74
- return err
75
- }
68
+ d.Next() // consume encoder name
69
+ if d.NextArg() {
70
+ return d.ArgErr()
71
+ }
72
+ err := ce.LogEncoderConfig.UnmarshalCaddyfile(d)
73
+ if err != nil {
74
+ return err
75
}
76
return nil
77
}
@@ -106,14 +105,13 @@ func (je *JSONEncoder) Provision(_ caddy.Context) error {
105
// See the godoc on the LogEncoderConfig type for the syntax of
106
// subdirectives that are common to most/all encoders.
107
func (je *JSONEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
109
- for d.Next() {
110
- if d.NextArg() {
111
- return d.ArgErr()
112
- }
113
- err := je.LogEncoderConfig.UnmarshalCaddyfile(d)
114
- if err != nil {
115
- return err
116
- }
108
+ d.Next() // consume encoder name
109
+ if d.NextArg() {
110
+ return d.ArgErr()
111
+ }
112
+ err := je.LogEncoderConfig.UnmarshalCaddyfile(d)
113
+ if err != nil {
114
+ return err
115
}
116
return nil
117
}
@@ -149,7 +147,7 @@ type LogEncoderConfig struct {
147
// level_format <format>
148
// }
149
func (lec *LogEncoderConfig) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
152
- for nesting := d.Nesting(); d.NextBlock(nesting); {
150
+ for d.NextBlock(0) {
151
subdir := d.Val()
152
switch subdir {
153
case "time_local":
modules/logging/filewriter.go
+64
-65
@@ -154,73 +154,72 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
154
// omitted or set to a zero value, then Caddy's default value for that
155
// subdirective is used.
156
func (fw *FileWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
157
- for d.Next() {
158
- if !d.NextArg() {
159
- return d.ArgErr()
160
- }
161
- fw.Filename = d.Val()
162
- if d.NextArg() {
163
- return d.ArgErr()
164
- }
157
+ d.Next() // consume writer name
158
+ if !d.NextArg() {
159
+ return d.ArgErr()
160
+ }
161
+ fw.Filename = d.Val()
162
+ if d.NextArg() {
163
+ return d.ArgErr()
164
+ }
165
+
166
+ for d.NextBlock(0) {
167
+ switch d.Val() {
168
+ case "roll_disabled":
169
+ var f bool
170
+ fw.Roll = &f
171
+ if d.NextArg() {
172
+ return d.ArgErr()
173
+ }
174
+
175
+ case "roll_size":
176
+ var sizeStr string
177
+ if !d.AllArgs(&sizeStr) {
178
+ return d.ArgErr()
179
+ }
180
+ size, err := humanize.ParseBytes(sizeStr)
181
+ if err != nil {
182
+ return d.Errf("parsing size: %v", err)
183
+ }
184
+ fw.RollSizeMB = int(math.Ceil(float64(size) / humanize.MiByte))
185
166
- for d.NextBlock(0) {
167
- switch d.Val() {
168
- case "roll_disabled":
169
- var f bool
170
- fw.Roll = &f
171
- if d.NextArg() {
172
- return d.ArgErr()
173
- }
174
-
175
- case "roll_size":
176
- var sizeStr string
177
- if !d.AllArgs(&sizeStr) {
178
- return d.ArgErr()
179
- }
180
- size, err := humanize.ParseBytes(sizeStr)
181
- if err != nil {
182
- return d.Errf("parsing size: %v", err)
183
- }
184
- fw.RollSizeMB = int(math.Ceil(float64(size) / humanize.MiByte))
185
-
186
- case "roll_uncompressed":
187
- var f bool
188
- fw.RollCompress = &f
189
- if d.NextArg() {
190
- return d.ArgErr()
191
- }
192
-
193
- case "roll_local_time":
194
- fw.RollLocalTime = true
195
- if d.NextArg() {
196
- return d.ArgErr()
197
- }
198
-
199
- case "roll_keep":
200
- var keepStr string
201
- if !d.AllArgs(&keepStr) {
202
- return d.ArgErr()
203
- }
204
- keep, err := strconv.Atoi(keepStr)
205
- if err != nil {
206
- return d.Errf("parsing roll_keep number: %v", err)
207
- }
208
- fw.RollKeep = keep
209
-
210
- case "roll_keep_for":
211
- var keepForStr string
212
- if !d.AllArgs(&keepForStr) {
213
- return d.ArgErr()
214
- }
215
- keepFor, err := caddy.ParseDuration(keepForStr)
216
- if err != nil {
217
- return d.Errf("parsing roll_keep_for duration: %v", err)
218
- }
219
- if keepFor < 0 {
220
- return d.Errf("negative roll_keep_for duration: %v", keepFor)
221
- }
222
- fw.RollKeepDays = int(math.Ceil(keepFor.Hours() / 24))
186
+ case "roll_uncompressed":
187
+ var f bool
188
+ fw.RollCompress = &f
189
+ if d.NextArg() {
190
+ return d.ArgErr()
191
+ }
192
+
193
+ case "roll_local_time":
194
+ fw.RollLocalTime = true
195
+ if d.NextArg() {
196
+ return d.ArgErr()
197
+ }
198
+
199
+ case "roll_keep":
200
+ var keepStr string
201
+ if !d.AllArgs(&keepStr) {
202
+ return d.ArgErr()
203
+ }
204
+ keep, err := strconv.Atoi(keepStr)
205
+ if err != nil {
206
+ return d.Errf("parsing roll_keep number: %v", err)
207
+ }
208
+ fw.RollKeep = keep
209
+
210
+ case "roll_keep_for":
211
+ var keepForStr string
212
+ if !d.AllArgs(&keepForStr) {
213
+ return d.ArgErr()
214
+ }
215
+ keepFor, err := caddy.ParseDuration(keepForStr)
216
+ if err != nil {
217
+ return d.Errf("parsing roll_keep_for duration: %v", err)
218
+ }
219
+ if keepFor < 0 {
220
+ return d.Errf("negative roll_keep_for duration: %v", keepFor)
221
}
222
+ fw.RollKeepDays = int(math.Ceil(keepFor.Hours() / 24))
223
}
224
}
225
return nil
modules/logging/filterencoder.go
+32
-33
@@ -108,50 +108,49 @@ func (fe *FilterEncoder) Provision(ctx caddy.Context) error {
108
// }
109
// }
110
func (fe *FilterEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
111
- for d.Next() {
112
- for d.NextBlock(0) {
113
- switch d.Val() {
114
- case "wrap":
111
+ d.Next() // consume encoder name
112
+ for d.NextBlock(0) {
113
+ switch d.Val() {
114
+ case "wrap":
115
+ if !d.NextArg() {
116
+ return d.ArgErr()
117
+ }
118
+ moduleName := d.Val()
119
+ moduleID := "caddy.logging.encoders." + moduleName
120
+ unm, err := caddyfile.UnmarshalModule(d, moduleID)
121
+ if err != nil {
122
+ return err
123
+ }
124
+ enc, ok := unm.(zapcore.Encoder)
125
+ if !ok {
126
+ return d.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
127
+ }
128
+ fe.WrappedRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, nil)
129
+
130
+ case "fields":
131
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
132
+ field := d.Val()
133
if !d.NextArg() {
134
return d.ArgErr()
135
}
118
- moduleName := d.Val()
119
- moduleID := "caddy.logging.encoders." + moduleName
136
+ filterName := d.Val()
137
+ moduleID := "caddy.logging.encoders.filter." + filterName
138
unm, err := caddyfile.UnmarshalModule(d, moduleID)
139
if err != nil {
140
return err
141
}
124
- enc, ok := unm.(zapcore.Encoder)
142
+ filter, ok := unm.(LogFieldFilter)
143
if !ok {
126
- return d.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
144
+ return d.Errf("module %s (%T) is not a logging.LogFieldFilter", moduleID, unm)
145
}
128
- fe.WrappedRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, nil)
129
-
130
- case "fields":
131
- for d.NextBlock(1) {
132
- field := d.Val()
133
- if !d.NextArg() {
134
- return d.ArgErr()
135
- }
136
- filterName := d.Val()
137
- moduleID := "caddy.logging.encoders.filter." + filterName
138
- unm, err := caddyfile.UnmarshalModule(d, moduleID)
139
- if err != nil {
140
- return err
141
- }
142
- filter, ok := unm.(LogFieldFilter)
143
- if !ok {
144
- return d.Errf("module %s (%T) is not a logging.LogFieldFilter", moduleID, unm)
145
- }
146
- if fe.FieldsRaw == nil {
147
- fe.FieldsRaw = make(map[string]json.RawMessage)
148
- }
149
- fe.FieldsRaw[field] = caddyconfig.JSONModuleObject(filter, "filter", filterName, nil)
146
+ if fe.FieldsRaw == nil {
147
+ fe.FieldsRaw = make(map[string]json.RawMessage)
148
}
151
-
152
- default:
153
- return d.Errf("unrecognized subdirective %s", d.Val())
149
+ fe.FieldsRaw[field] = caddyconfig.JSONModuleObject(filter, "filter", filterName, nil)
150
}
151
+
152
+ default:
153
+ return d.Errf("unrecognized subdirective %s", d.Val())
154
}
155
}
156
return nil
modules/logging/filters.go
+106
-112
@@ -128,10 +128,9 @@ func (ReplaceFilter) CaddyModule() caddy.ModuleInfo {
128
129
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
130
func (f *ReplaceFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
131
- for d.Next() {
132
- if d.NextArg() {
133
- f.Value = d.Val()
134
- }
131
+ d.Next() // consume filter name
132
+ if d.NextArg() {
133
+ f.Value = d.Val()
134
}
135
return nil
136
}
@@ -169,32 +168,31 @@ func (IPMaskFilter) CaddyModule() caddy.ModuleInfo {
168
169
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
170
func (m *IPMaskFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
172
- for d.Next() {
173
- for d.NextBlock(0) {
174
- switch d.Val() {
175
- case "ipv4":
176
- if !d.NextArg() {
177
- return d.ArgErr()
178
- }
179
- val, err := strconv.Atoi(d.Val())
180
- if err != nil {
181
- return d.Errf("error parsing %s: %v", d.Val(), err)
182
- }
183
- m.IPv4MaskRaw = val
184
-
185
- case "ipv6":
186
- if !d.NextArg() {
187
- return d.ArgErr()
188
- }
189
- val, err := strconv.Atoi(d.Val())
190
- if err != nil {
191
- return d.Errf("error parsing %s: %v", d.Val(), err)
192
- }
193
- m.IPv6MaskRaw = val
194
-
195
- default:
196
- return d.Errf("unrecognized subdirective %s", d.Val())
171
+ d.Next() // consume filter name
172
+ for d.NextBlock(0) {
173
+ switch d.Val() {
174
+ case "ipv4":
175
+ if !d.NextArg() {
176
+ return d.ArgErr()
177
+ }
178
+ val, err := strconv.Atoi(d.Val())
179
+ if err != nil {
180
+ return d.Errf("error parsing %s: %v", d.Val(), err)
181
+ }
182
+ m.IPv4MaskRaw = val
183
+
184
+ case "ipv6":
185
+ if !d.NextArg() {
186
+ return d.ArgErr()
187
}
188
+ val, err := strconv.Atoi(d.Val())
189
+ if err != nil {
190
+ return d.Errf("error parsing %s: %v", d.Val(), err)
191
+ }
192
+ m.IPv6MaskRaw = val
193
+
194
+ default:
195
+ return d.Errf("unrecognized subdirective %s", d.Val())
196
}
197
}
198
return nil
@@ -328,45 +326,44 @@ func (QueryFilter) CaddyModule() caddy.ModuleInfo {
326
327
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
328
func (m *QueryFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
331
- for d.Next() {
332
- for d.NextBlock(0) {
333
- qfa := queryFilterAction{}
334
- switch d.Val() {
335
- case "replace":
336
- if !d.NextArg() {
337
- return d.ArgErr()
338
- }
339
-
340
- qfa.Type = replaceAction
341
- qfa.Parameter = d.Val()
342
-
343
- if !d.NextArg() {
344
- return d.ArgErr()
345
- }
346
- qfa.Value = d.Val()
347
-
348
- case "hash":
349
- if !d.NextArg() {
350
- return d.ArgErr()
351
- }
352
-
353
- qfa.Type = hashAction
354
- qfa.Parameter = d.Val()
355
-
356
- case "delete":
357
- if !d.NextArg() {
358
- return d.ArgErr()
359
- }
360
-
361
- qfa.Type = deleteAction
362
- qfa.Parameter = d.Val()
363
-
364
- default:
365
- return d.Errf("unrecognized subdirective %s", d.Val())
329
+ d.Next() // consume filter name
330
+ for d.NextBlock(0) {
331
+ qfa := queryFilterAction{}
332
+ switch d.Val() {
333
+ case "replace":
334
+ if !d.NextArg() {
335
+ return d.ArgErr()
336
}
337
368
- m.Actions = append(m.Actions, qfa)
338
+ qfa.Type = replaceAction
339
+ qfa.Parameter = d.Val()
340
+
341
+ if !d.NextArg() {
342
+ return d.ArgErr()
343
+ }
344
+ qfa.Value = d.Val()
345
+
346
+ case "hash":
347
+ if !d.NextArg() {
348
+ return d.ArgErr()
349
+ }
350
+
351
+ qfa.Type = hashAction
352
+ qfa.Parameter = d.Val()
353
+
354
+ case "delete":
355
+ if !d.NextArg() {
356
+ return d.ArgErr()
357
+ }
358
+
359
+ qfa.Type = deleteAction
360
+ qfa.Parameter = d.Val()
361
+
362
+ default:
363
+ return d.Errf("unrecognized subdirective %s", d.Val())
364
}
365
+
366
+ m.Actions = append(m.Actions, qfa)
367
}
368
return nil
369
}
@@ -460,45 +457,44 @@ func (CookieFilter) CaddyModule() caddy.ModuleInfo {
457
458
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
459
func (m *CookieFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
463
- for d.Next() {
464
- for d.NextBlock(0) {
465
- cfa := cookieFilterAction{}
466
- switch d.Val() {
467
- case "replace":
468
- if !d.NextArg() {
469
- return d.ArgErr()
470
- }
471
-
472
- cfa.Type = replaceAction
473
- cfa.Name = d.Val()
474
-
475
- if !d.NextArg() {
476
- return d.ArgErr()
477
- }
478
- cfa.Value = d.Val()
479
-
480
- case "hash":
481
- if !d.NextArg() {
482
- return d.ArgErr()
483
- }
484
-
485
- cfa.Type = hashAction
486
- cfa.Name = d.Val()
487
-
488
- case "delete":
489
- if !d.NextArg() {
490
- return d.ArgErr()
491
- }
492
-
493
- cfa.Type = deleteAction
494
- cfa.Name = d.Val()
495
-
496
- default:
497
- return d.Errf("unrecognized subdirective %s", d.Val())
460
+ d.Next() // consume filter name
461
+ for d.NextBlock(0) {
462
+ cfa := cookieFilterAction{}
463
+ switch d.Val() {
464
+ case "replace":
465
+ if !d.NextArg() {
466
+ return d.ArgErr()
467
+ }
468
+
469
+ cfa.Type = replaceAction
470
+ cfa.Name = d.Val()
471
+
472
+ if !d.NextArg() {
473
+ return d.ArgErr()
474
}
475
+ cfa.Value = d.Val()
476
500
- m.Actions = append(m.Actions, cfa)
477
+ case "hash":
478
+ if !d.NextArg() {
479
+ return d.ArgErr()
480
+ }
481
+
482
+ cfa.Type = hashAction
483
+ cfa.Name = d.Val()
484
+
485
+ case "delete":
486
+ if !d.NextArg() {
487
+ return d.ArgErr()
488
+ }
489
+
490
+ cfa.Type = deleteAction
491
+ cfa.Name = d.Val()
492
+
493
+ default:
494
+ return d.Errf("unrecognized subdirective %s", d.Val())
495
}
496
+
497
+ m.Actions = append(m.Actions, cfa)
498
}
499
return nil
500
}
@@ -571,13 +567,12 @@ func (RegexpFilter) CaddyModule() caddy.ModuleInfo {
567
568
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
569
func (f *RegexpFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
574
- for d.Next() {
575
- if d.NextArg() {
576
- f.RawRegexp = d.Val()
577
- }
578
- if d.NextArg() {
579
- f.Value = d.Val()
580
- }
570
+ d.Next() // consume filter name
571
+ if d.NextArg() {
572
+ f.RawRegexp = d.Val()
573
+ }
574
+ if d.NextArg() {
575
+ f.Value = d.Val()
576
}
577
return nil
578
}
@@ -625,10 +620,9 @@ func (RenameFilter) CaddyModule() caddy.ModuleInfo {
620
621
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
622
func (f *RenameFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
628
- for d.Next() {
629
- if d.NextArg() {
630
- f.Name = d.Val()
631
- }
623
+ d.Next() // consume filter name
624
+ if d.NextArg() {
625
+ f.Name = d.Val()
626
}
627
return nil
628
}
modules/logging/netwriter.go
+27
-28
@@ -117,35 +117,34 @@ func (nw NetWriter) OpenWriter() (io.WriteCloser, error) {
117
// soft_start
118
// }
119
func (nw *NetWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
120
- for d.Next() {
121
- if !d.NextArg() {
122
- return d.ArgErr()
123
- }
124
- nw.Address = d.Val()
125
- if d.NextArg() {
126
- return d.ArgErr()
127
- }
128
- for nesting := d.Nesting(); d.NextBlock(nesting); {
129
- switch d.Val() {
130
- case "dial_timeout":
131
- if !d.NextArg() {
132
- return d.ArgErr()
133
- }
134
- timeout, err := caddy.ParseDuration(d.Val())
135
- if err != nil {
136
- return d.Errf("invalid duration: %s", d.Val())
137
- }
138
- if d.NextArg() {
139
- return d.ArgErr()
140
- }
141
- nw.DialTimeout = caddy.Duration(timeout)
142
-
143
- case "soft_start":
144
- if d.NextArg() {
145
- return d.ArgErr()
146
- }
147
- nw.SoftStart = true
120
+ d.Next() // consume writer name
121
+ if !d.NextArg() {
122
+ return d.ArgErr()
123
+ }
124
+ nw.Address = d.Val()
125
+ if d.NextArg() {
126
+ return d.ArgErr()
127
+ }
128
+ for d.NextBlock(0) {
129
+ switch d.Val() {
130
+ case "dial_timeout":
131
+ if !d.NextArg() {
132
+ return d.ArgErr()
133
+ }
134
+ timeout, err := caddy.ParseDuration(d.Val())
135
+ if err != nil {
136
+ return d.Errf("invalid duration: %s", d.Val())
137
+ }
138
+ if d.NextArg() {
139
+ return d.ArgErr()
140
+ }
141
+ nw.DialTimeout = caddy.Duration(timeout)
142
+
143
+ case "soft_start":
144
+ if d.NextArg() {
145
+ return d.ArgErr()
146
}
147
+ nw.SoftStart = true
148
}
149
}
150
return nil
modules/metrics/metrics.go
+11
-12
@@ -78,19 +78,18 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
78
// disable_openmetrics
79
// }
80
func (m *Metrics) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
81
- for d.Next() {
82
- args := d.RemainingArgs()
83
- if len(args) > 0 {
84
- return d.ArgErr()
85
- }
81
+ d.Next() // consume directive name
82
+ args := d.RemainingArgs()
83
+ if len(args) > 0 {
84
+ return d.ArgErr()
85
+ }
86
87
- for d.NextBlock(0) {
88
- switch d.Val() {
89
- case "disable_openmetrics":
90
- m.DisableOpenMetrics = true
91
- default:
92
- return d.Errf("unrecognized subdirective %q", d.Val())
93
- }
87
+ for d.NextBlock(0) {
88
+ switch d.Val() {
89
+ case "disable_openmetrics":
90
+ m.DisableOpenMetrics = true
91
+ default:
92
+ return d.Errf("unrecognized subdirective %q", d.Val())
93
}
94
}
95
return nil