aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--caddyconfig/caddyfile/adapter.go32
-rw-r--r--caddyconfig/httpcaddyfile/builtins.go1086
-rw-r--r--caddyconfig/httpcaddyfile/directives.go6
-rw-r--r--caddyconfig/httpcaddyfile/httptype.go109
-rw-r--r--caddyconfig/httpcaddyfile/options.go365
-rw-r--r--caddyconfig/httpcaddyfile/pkiapp.go196
-rw-r--r--caddyconfig/httpcaddyfile/serveroptions.go400
-rw-r--r--caddytest/integration/caddyfile_adapt/push.txt78
-rw-r--r--modules/caddyevents/eventsconfig/caddyfile.go8
-rw-r--r--modules/caddyhttp/caddyauth/caddyfile.go80
-rw-r--r--modules/caddyhttp/celmatcher.go26
-rw-r--r--modules/caddyhttp/encode/caddyfile.go92
-rw-r--r--modules/caddyhttp/encode/gzip/gzip.go19
-rw-r--r--modules/caddyhttp/fileserver/caddyfile.go2
-rw-r--r--modules/caddyhttp/fileserver/matcher.go1
-rw-r--r--modules/caddyhttp/headers/caddyfile.go188
-rw-r--r--modules/caddyhttp/ip_matchers.go48
-rw-r--r--modules/caddyhttp/map/caddyfile.go109
-rw-r--r--modules/caddyhttp/matchers.go9
-rw-r--r--modules/caddyhttp/proxyprotocol/module.go60
-rw-r--r--modules/caddyhttp/push/caddyfile.go90
-rw-r--r--modules/caddyhttp/requestbody/caddyfile.go33
-rw-r--r--modules/caddyhttp/responsematchers.go78
-rw-r--r--modules/caddyhttp/reverseproxy/caddyfile.go934
-rw-r--r--modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go123
-rw-r--r--modules/caddyhttp/reverseproxy/selectionpolicies.go125
-rw-r--r--modules/caddyhttp/rewrite/caddyfile.go159
-rw-r--r--modules/caddyhttp/staticerror.go51
-rw-r--r--modules/caddyhttp/staticresp.go61
-rw-r--r--modules/caddyhttp/templates/caddyfile.go73
-rw-r--r--modules/caddyhttp/tracing/module.go22
-rw-r--r--modules/caddyhttp/vars.go16
-rw-r--r--modules/caddypki/acmeserver/caddyfile.go77
-rw-r--r--modules/caddytls/acmeissuer.go383
-rw-r--r--modules/caddytls/certmanagers.go30
-rw-r--r--modules/caddytls/internalissuer.go45
-rw-r--r--modules/caddytls/zerosslissuer.go23
-rw-r--r--modules/filestorage/filestorage.go2
-rw-r--r--modules/logging/encoders.go32
-rw-r--r--modules/logging/filewriter.go129
-rw-r--r--modules/logging/filterencoder.go65
-rw-r--r--modules/logging/filters.go218
-rw-r--r--modules/logging/netwriter.go55
-rw-r--r--modules/metrics/metrics.go23
44 files changed, 2887 insertions, 2874 deletions
diff --git a/caddyconfig/caddyfile/adapter.go b/caddyconfig/caddyfile/adapter.go
index d6ef602dc..edd825b88 100644
--- a/caddyconfig/caddyfile/adapter.go
+++ b/caddyconfig/caddyfile/adapter.go
@@ -92,30 +92,26 @@ func FormattingDifference(filename string, body []byte) (caddyconfig.Warning, bo
}, true
}
-// Unmarshaler is a type that can unmarshal
-// Caddyfile tokens to set itself up for a
-// JSON encoding. The goal of an unmarshaler
-// is not to set itself up for actual use,
-// but to set itself up for being marshaled
-// into JSON. Caddyfile-unmarshaled values
-// will not be used directly; they will be
-// encoded as JSON and then used from that.
-// Implementations must be able to support
-// multiple segments (instances of their
-// directive or batch of tokens); typically
-// this means wrapping all token logic in
-// a loop: `for d.Next() { ... }`.
+// Unmarshaler is a type that can unmarshal Caddyfile tokens to
+// set itself up for a JSON encoding. The goal of an unmarshaler
+// is not to set itself up for actual use, but to set itself up for
+// being marshaled into JSON. Caddyfile-unmarshaled values will not
+// be used directly; they will be encoded as JSON and then used from
+// that. Implementations _may_ be able to support multiple segments
+// (instances of their directive or batch of tokens); typically this
+// means wrapping parsing logic in a loop: `for d.Next() { ... }`.
+// More commonly, only a single segment is supported, so a simple
+// `d.Next()` at the start should be used to consume the module
+// identifier token (directive name, etc).
type Unmarshaler interface {
UnmarshalCaddyfile(d *Dispenser) error
}
// ServerType is a type that can evaluate a Caddyfile and set up a caddy config.
type ServerType interface {
- // Setup takes the server blocks which
- // contain tokens, as well as options
- // (e.g. CLI flags) and creates a Caddy
- // config, along with any warnings or
- // an error.
+ // Setup takes the server blocks which contain tokens,
+ // as well as options (e.g. CLI flags) and creates a
+ // Caddy config, along with any warnings or an error.
Setup([]ServerBlock, map[string]any) (*caddy.Config, []caddyconfig.Warning, error)
}
diff --git a/caddyconfig/httpcaddyfile/builtins.go b/caddyconfig/httpcaddyfile/builtins.go
index bf95a3616..11d18caea 100644
--- a/caddyconfig/httpcaddyfile/builtins.go
+++ b/caddyconfig/httpcaddyfile/builtins.go
@@ -59,11 +59,8 @@ func init() {
//
// bind <addresses...>
func parseBind(h Helper) ([]ConfigValue, error) {
- var lnHosts []string
- for h.Next() {
- lnHosts = append(lnHosts, h.RemainingArgs()...)
- }
- return h.NewBindAddresses(lnHosts), nil
+ h.Next() // consume directive name
+ return []ConfigValue{{Class: "bind", Value: h.RemainingArgs()}}, nil
}
// parseTLS parses the tls directive. Syntax:
@@ -98,6 +95,8 @@ func parseBind(h Helper) ([]ConfigValue, error) {
// insecure_secrets_log <log_file>
// }
func parseTLS(h Helper) ([]ConfigValue, error) {
+ h.Next() // consume directive name
+
cp := new(caddytls.ConnectionPolicy)
var fileLoader caddytls.FileLoader
var folderLoader caddytls.FolderLoader
@@ -110,423 +109,421 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
var onDemand bool
var reusePrivateKeys bool
- for h.Next() {
- // file certificate loader
- firstLine := h.RemainingArgs()
- switch len(firstLine) {
- case 0:
- case 1:
- if firstLine[0] == "internal" {
- internalIssuer = new(caddytls.InternalIssuer)
- } else if !strings.Contains(firstLine[0], "@") {
- return nil, h.Err("single argument must either be 'internal' or an email address")
- } else {
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
- }
- acmeIssuer.Email = firstLine[0]
- }
-
- case 2:
- certFilename := firstLine[0]
- keyFilename := firstLine[1]
-
- // tag this certificate so if multiple certs match, specifically
- // this one that the user has provided will be used, see #2588:
- // https://github.com/caddyserver/caddy/issues/2588 ... but we
- // must be careful about how we do this; being careless will
- // lead to failed handshakes
- //
- // we need to remember which cert files we've seen, since we
- // must load each cert only once; otherwise, they each get a
- // different tag... since a cert loaded twice has the same
- // bytes, it will overwrite the first one in the cache, and
- // only the last cert (and its tag) will survive, so any conn
- // policy that is looking for any tag other than the last one
- // to be loaded won't find it, and TLS handshakes will fail
- // (see end of issue #3004)
- //
- // tlsCertTags maps certificate filenames to their tag.
- // This is used to remember which tag is used for each
- // certificate files, since we need to avoid loading
- // the same certificate files more than once, overwriting
- // previous tags
- tlsCertTags, ok := h.State["tlsCertTags"].(map[string]string)
- if !ok {
- tlsCertTags = make(map[string]string)
- h.State["tlsCertTags"] = tlsCertTags
+ // file certificate loader
+ firstLine := h.RemainingArgs()
+ switch len(firstLine) {
+ case 0:
+ case 1:
+ if firstLine[0] == "internal" {
+ internalIssuer = new(caddytls.InternalIssuer)
+ } else if !strings.Contains(firstLine[0], "@") {
+ return nil, h.Err("single argument must either be 'internal' or an email address")
+ } else {
+ if acmeIssuer == nil {
+ acmeIssuer = new(caddytls.ACMEIssuer)
}
+ acmeIssuer.Email = firstLine[0]
+ }
- tag, ok := tlsCertTags[certFilename]
- if !ok {
- // haven't seen this cert file yet, let's give it a tag
- // and add a loader for it
- tag = fmt.Sprintf("cert%d", len(tlsCertTags))
- fileLoader = append(fileLoader, caddytls.CertKeyFilePair{
- Certificate: certFilename,
- Key: keyFilename,
- Tags: []string{tag},
- })
- // remember this for next time we see this cert file
- tlsCertTags[certFilename] = tag
- }
- certSelector.AnyTag = append(certSelector.AnyTag, tag)
+ case 2:
+ certFilename := firstLine[0]
+ keyFilename := firstLine[1]
+
+ // tag this certificate so if multiple certs match, specifically
+ // this one that the user has provided will be used, see #2588:
+ // https://github.com/caddyserver/caddy/issues/2588 ... but we
+ // must be careful about how we do this; being careless will
+ // lead to failed handshakes
+ //
+ // we need to remember which cert files we've seen, since we
+ // must load each cert only once; otherwise, they each get a
+ // different tag... since a cert loaded twice has the same
+ // bytes, it will overwrite the first one in the cache, and
+ // only the last cert (and its tag) will survive, so any conn
+ // policy that is looking for any tag other than the last one
+ // to be loaded won't find it, and TLS handshakes will fail
+ // (see end of issue #3004)
+ //
+ // tlsCertTags maps certificate filenames to their tag.
+ // This is used to remember which tag is used for each
+ // certificate files, since we need to avoid loading
+ // the same certificate files more than once, overwriting
+ // previous tags
+ tlsCertTags, ok := h.State["tlsCertTags"].(map[string]string)
+ if !ok {
+ tlsCertTags = make(map[string]string)
+ h.State["tlsCertTags"] = tlsCertTags
+ }
- default:
- return nil, h.ArgErr()
+ tag, ok := tlsCertTags[certFilename]
+ if !ok {
+ // haven't seen this cert file yet, let's give it a tag
+ // and add a loader for it
+ tag = fmt.Sprintf("cert%d", len(tlsCertTags))
+ fileLoader = append(fileLoader, caddytls.CertKeyFilePair{
+ Certificate: certFilename,
+ Key: keyFilename,
+ Tags: []string{tag},
+ })
+ // remember this for next time we see this cert file
+ tlsCertTags[certFilename] = tag
}
+ certSelector.AnyTag = append(certSelector.AnyTag, tag)
- var hasBlock bool
- for nesting := h.Nesting(); h.NextBlock(nesting); {
- hasBlock = true
+ default:
+ return nil, h.ArgErr()
+ }
+
+ var hasBlock bool
+ for h.NextBlock(0) {
+ hasBlock = true
- switch h.Val() {
- case "protocols":
- args := h.RemainingArgs()
- if len(args) == 0 {
- return nil, h.Errf("protocols requires one or two arguments")
+ switch h.Val() {
+ case "protocols":
+ args := h.RemainingArgs()
+ if len(args) == 0 {
+ return nil, h.Errf("protocols requires one or two arguments")
+ }
+ if len(args) > 0 {
+ if _, ok := caddytls.SupportedProtocols[args[0]]; !ok {
+ return nil, h.Errf("wrong protocol name or protocol not supported: '%s'", args[0])
}
- if len(args) > 0 {
- if _, ok := caddytls.SupportedProtocols[args[0]]; !ok {
- return nil, h.Errf("wrong protocol name or protocol not supported: '%s'", args[0])
- }
- cp.ProtocolMin = args[0]
+ cp.ProtocolMin = args[0]
+ }
+ if len(args) > 1 {
+ if _, ok := caddytls.SupportedProtocols[args[1]]; !ok {
+ return nil, h.Errf("wrong protocol name or protocol not supported: '%s'", args[1])
}
- if len(args) > 1 {
- if _, ok := caddytls.SupportedProtocols[args[1]]; !ok {
- return nil, h.Errf("wrong protocol name or protocol not supported: '%s'", args[1])
- }
- cp.ProtocolMax = args[1]
+ cp.ProtocolMax = args[1]
+ }
+
+ case "ciphers":
+ for h.NextArg() {
+ if !caddytls.CipherSuiteNameSupported(h.Val()) {
+ return nil, h.Errf("wrong cipher suite name or cipher suite not supported: '%s'", h.Val())
}
+ cp.CipherSuites = append(cp.CipherSuites, h.Val())
+ }
- case "ciphers":
- for h.NextArg() {
- if !caddytls.CipherSuiteNameSupported(h.Val()) {
- return nil, h.Errf("wrong cipher suite name or cipher suite not supported: '%s'", h.Val())
- }
- cp.CipherSuites = append(cp.CipherSuites, h.Val())
+ case "curves":
+ for h.NextArg() {
+ if _, ok := caddytls.SupportedCurves[h.Val()]; !ok {
+ return nil, h.Errf("Wrong curve name or curve not supported: '%s'", h.Val())
}
+ cp.Curves = append(cp.Curves, h.Val())
+ }
- case "curves":
- for h.NextArg() {
- if _, ok := caddytls.SupportedCurves[h.Val()]; !ok {
- return nil, h.Errf("Wrong curve name or curve not supported: '%s'", h.Val())
+ case "client_auth":
+ cp.ClientAuthentication = &caddytls.ClientAuthentication{}
+ for nesting := h.Nesting(); h.NextBlock(nesting); {
+ subdir := h.Val()
+ switch subdir {
+ case "verifier":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
}
- cp.Curves = append(cp.Curves, h.Val())
- }
- case "client_auth":
- cp.ClientAuthentication = &caddytls.ClientAuthentication{}
- for nesting := h.Nesting(); h.NextBlock(nesting); {
- subdir := h.Val()
- switch subdir {
- case "verifier":
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
+ vType := h.Val()
+ modID := "tls.client_auth." + vType
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
+ if err != nil {
+ return nil, err
+ }
- vType := h.Val()
- modID := "tls.client_auth." + vType
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
- if err != nil {
- return nil, err
- }
+ _, ok := unm.(caddytls.ClientCertificateVerifier)
+ if !ok {
+ return nil, h.Dispenser.Errf("module %s is not a caddytls.ClientCertificatVerifier", modID)
+ }
- _, ok := unm.(caddytls.ClientCertificateVerifier)
- if !ok {
- return nil, h.Dispenser.Errf("module %s is not a caddytls.ClientCertificatVerifier", modID)
- }
+ cp.ClientAuthentication.VerifiersRaw = append(cp.ClientAuthentication.VerifiersRaw, caddyconfig.JSONModuleObject(unm, "verifier", vType, h.warnings))
+ case "mode":
+ if !h.Args(&cp.ClientAuthentication.Mode) {
+ return nil, h.ArgErr()
+ }
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
- cp.ClientAuthentication.VerifiersRaw = append(cp.ClientAuthentication.VerifiersRaw, caddyconfig.JSONModuleObject(unm, "verifier", vType, h.warnings))
- case "mode":
- if !h.Args(&cp.ClientAuthentication.Mode) {
- return nil, h.ArgErr()
- }
- if h.NextArg() {
- return nil, h.ArgErr()
- }
+ case "trusted_ca_cert",
+ "trusted_leaf_cert":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ if subdir == "trusted_ca_cert" {
+ cp.ClientAuthentication.TrustedCACerts = append(cp.ClientAuthentication.TrustedCACerts, h.Val())
+ } else {
+ cp.ClientAuthentication.TrustedLeafCerts = append(cp.ClientAuthentication.TrustedLeafCerts, h.Val())
+ }
- case "trusted_ca_cert",
- "trusted_leaf_cert":
- if !h.NextArg() {
- return nil, h.ArgErr()
+ case "trusted_ca_cert_file",
+ "trusted_leaf_cert_file":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ filename := h.Val()
+ certDataPEM, err := os.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ // while block is not nil, we have more certificates in the file
+ for block, rest := pem.Decode(certDataPEM); block != nil; block, rest = pem.Decode(rest) {
+ if block.Type != "CERTIFICATE" {
+ return nil, h.Errf("no CERTIFICATE pem block found in %s", filename)
}
- if subdir == "trusted_ca_cert" {
- cp.ClientAuthentication.TrustedCACerts = append(cp.ClientAuthentication.TrustedCACerts, h.Val())
+ if subdir == "trusted_ca_cert_file" {
+ cp.ClientAuthentication.TrustedCACerts = append(
+ cp.ClientAuthentication.TrustedCACerts,
+ base64.StdEncoding.EncodeToString(block.Bytes),
+ )
} else {
- cp.ClientAuthentication.TrustedLeafCerts = append(cp.ClientAuthentication.TrustedLeafCerts, h.Val())
- }
-
- case "trusted_ca_cert_file",
- "trusted_leaf_cert_file":
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- filename := h.Val()
- certDataPEM, err := os.ReadFile(filename)
- if err != nil {
- return nil, err
+ cp.ClientAuthentication.TrustedLeafCerts = append(
+ cp.ClientAuthentication.TrustedLeafCerts,
+ base64.StdEncoding.EncodeToString(block.Bytes),
+ )
}
- // while block is not nil, we have more certificates in the file
- for block, rest := pem.Decode(certDataPEM); block != nil; block, rest = pem.Decode(rest) {
- if block.Type != "CERTIFICATE" {
- return nil, h.Errf("no CERTIFICATE pem block found in %s", filename)
- }
- if subdir == "trusted_ca_cert_file" {
- cp.ClientAuthentication.TrustedCACerts = append(
- cp.ClientAuthentication.TrustedCACerts,
- base64.StdEncoding.EncodeToString(block.Bytes),
- )
- } else {
- cp.ClientAuthentication.TrustedLeafCerts = append(
- cp.ClientAuthentication.TrustedLeafCerts,
- base64.StdEncoding.EncodeToString(block.Bytes),
- )
- }
- }
- // if we decoded nothing, return an error
- if len(cp.ClientAuthentication.TrustedCACerts) == 0 && len(cp.ClientAuthentication.TrustedLeafCerts) == 0 {
- return nil, h.Errf("no CERTIFICATE pem block found in %s", filename)
- }
-
- default:
- return nil, h.Errf("unknown subdirective for client_auth: %s", subdir)
}
- }
+ // if we decoded nothing, return an error
+ if len(cp.ClientAuthentication.TrustedCACerts) == 0 && len(cp.ClientAuthentication.TrustedLeafCerts) == 0 {
+ return nil, h.Errf("no CERTIFICATE pem block found in %s", filename)
+ }
- case "alpn":
- args := h.RemainingArgs()
- if len(args) == 0 {
- return nil, h.ArgErr()
+ default:
+ return nil, h.Errf("unknown subdirective for client_auth: %s", subdir)
}
- cp.ALPN = args
+ }
- case "load":
- folderLoader = append(folderLoader, h.RemainingArgs()...)
+ case "alpn":
+ args := h.RemainingArgs()
+ if len(args) == 0 {
+ return nil, h.ArgErr()
+ }
+ cp.ALPN = args
- case "ca":
- arg := h.RemainingArgs()
- if len(arg) != 1 {
- return nil, h.ArgErr()
- }
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
- }
- acmeIssuer.CA = arg[0]
+ case "load":
+ folderLoader = append(folderLoader, h.RemainingArgs()...)
- case "key_type":
- arg := h.RemainingArgs()
- if len(arg) != 1 {
- return nil, h.ArgErr()
- }
- keyType = arg[0]
+ case "ca":
+ arg := h.RemainingArgs()
+ if len(arg) != 1 {
+ return nil, h.ArgErr()
+ }
+ if acmeIssuer == nil {
+ acmeIssuer = new(caddytls.ACMEIssuer)
+ }
+ acmeIssuer.CA = arg[0]
- case "eab":
- arg := h.RemainingArgs()
- if len(arg) != 2 {
- return nil, h.ArgErr()
- }
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
- }
- acmeIssuer.ExternalAccount = &acme.EAB{
- KeyID: arg[0],
- MACKey: arg[1],
- }
+ case "key_type":
+ arg := h.RemainingArgs()
+ if len(arg) != 1 {
+ return nil, h.ArgErr()
+ }
+ keyType = arg[0]
- case "issuer":
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- modName := h.Val()
- modID := "tls.issuance." + modName
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
- if err != nil {
- return nil, err
- }
- issuer, ok := unm.(certmagic.Issuer)
- if !ok {
- return nil, h.Errf("module %s (%T) is not a certmagic.Issuer", modID, unm)
- }
- issuers = append(issuers, issuer)
+ case "eab":
+ arg := h.RemainingArgs()
+ if len(arg) != 2 {
+ return nil, h.ArgErr()
+ }
+ if acmeIssuer == nil {
+ acmeIssuer = new(caddytls.ACMEIssuer)
+ }
+ acmeIssuer.ExternalAccount = &acme.EAB{
+ KeyID: arg[0],
+ MACKey: arg[1],
+ }
- case "get_certificate":
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- modName := h.Val()
- modID := "tls.get_certificate." + modName
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
- if err != nil {
- return nil, err
- }
- certManager, ok := unm.(certmagic.Manager)
- if !ok {
- return nil, h.Errf("module %s (%T) is not a certmagic.CertificateManager", modID, unm)
- }
- certManagers = append(certManagers, certManager)
+ case "issuer":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ modName := h.Val()
+ modID := "tls.issuance." + modName
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
+ if err != nil {
+ return nil, err
+ }
+ issuer, ok := unm.(certmagic.Issuer)
+ if !ok {
+ return nil, h.Errf("module %s (%T) is not a certmagic.Issuer", modID, unm)
+ }
+ issuers = append(issuers, issuer)
- case "dns":
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- provName := h.Val()
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
- }
- if acmeIssuer.Challenges == nil {
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
- }
- if acmeIssuer.Challenges.DNS == nil {
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
- }
- modID := "dns.providers." + provName
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
- if err != nil {
- return nil, err
- }
- acmeIssuer.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, h.warnings)
+ case "get_certificate":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ modName := h.Val()
+ modID := "tls.get_certificate." + modName
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
+ if err != nil {
+ return nil, err
+ }
+ certManager, ok := unm.(certmagic.Manager)
+ if !ok {
+ return nil, h.Errf("module %s (%T) is not a certmagic.CertificateManager", modID, unm)
+ }
+ certManagers = append(certManagers, certManager)
- case "resolvers":
- args := h.RemainingArgs()
- if len(args) == 0 {
- return nil, h.ArgErr()
- }
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
- }
- if acmeIssuer.Challenges == nil {
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
- }
- if acmeIssuer.Challenges.DNS == nil {
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
- }
- acmeIssuer.Challenges.DNS.Resolvers = args
+ case "dns":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ provName := h.Val()
+ if acmeIssuer == nil {
+ acmeIssuer = new(caddytls.ACMEIssuer)
+ }
+ if acmeIssuer.Challenges == nil {
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
+ }
+ if acmeIssuer.Challenges.DNS == nil {
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
+ }
+ modID := "dns.providers." + provName
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
+ if err != nil {
+ return nil, err
+ }
+ acmeIssuer.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, h.warnings)
- case "propagation_delay":
- arg := h.RemainingArgs()
- if len(arg) != 1 {
- return nil, h.ArgErr()
- }
- delayStr := arg[0]
- delay, err := caddy.ParseDuration(delayStr)
- if err != nil {
- return nil, h.Errf("invalid propagation_delay duration %s: %v", delayStr, err)
- }
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
- }
- if acmeIssuer.Challenges == nil {
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
- }
- if acmeIssuer.Challenges.DNS == nil {
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
- }
- acmeIssuer.Challenges.DNS.PropagationDelay = caddy.Duration(delay)
+ case "resolvers":
+ args := h.RemainingArgs()
+ if len(args) == 0 {
+ return nil, h.ArgErr()
+ }
+ if acmeIssuer == nil {
+ acmeIssuer = new(caddytls.ACMEIssuer)
+ }
+ if acmeIssuer.Challenges == nil {
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
+ }
+ if acmeIssuer.Challenges.DNS == nil {
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
+ }
+ acmeIssuer.Challenges.DNS.Resolvers = args
- case "propagation_timeout":
- arg := h.RemainingArgs()
- if len(arg) != 1 {
- return nil, h.ArgErr()
- }
- timeoutStr := arg[0]
- var timeout time.Duration
- if timeoutStr == "-1" {
- timeout = time.Duration(-1)
- } else {
- var err error
- timeout, err = caddy.ParseDuration(timeoutStr)
- if err != nil {
- return nil, h.Errf("invalid propagation_timeout duration %s: %v", timeoutStr, err)
- }
- }
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
- }
- if acmeIssuer.Challenges == nil {
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
- }
- if acmeIssuer.Challenges.DNS == nil {
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
- }
- acmeIssuer.Challenges.DNS.PropagationTimeout = caddy.Duration(timeout)
+ case "propagation_delay":
+ arg := h.RemainingArgs()
+ if len(arg) != 1 {
+ return nil, h.ArgErr()
+ }
+ delayStr := arg[0]
+ delay, err := caddy.ParseDuration(delayStr)
+ if err != nil {
+ return nil, h.Errf("invalid propagation_delay duration %s: %v", delayStr, err)
+ }
+ if acmeIssuer == nil {
+ acmeIssuer = new(caddytls.ACMEIssuer)
+ }
+ if acmeIssuer.Challenges == nil {
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
+ }
+ if acmeIssuer.Challenges.DNS == nil {
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
+ }
+ acmeIssuer.Challenges.DNS.PropagationDelay = caddy.Duration(delay)
- case "dns_ttl":
- arg := h.RemainingArgs()
- if len(arg) != 1 {
- return nil, h.ArgErr()
- }
- ttlStr := arg[0]
- ttl, err := caddy.ParseDuration(ttlStr)
+ case "propagation_timeout":
+ arg := h.RemainingArgs()
+ if len(arg) != 1 {
+ return nil, h.ArgErr()
+ }
+ timeoutStr := arg[0]
+ var timeout time.Duration
+ if timeoutStr == "-1" {
+ timeout = time.Duration(-1)
+ } else {
+ var err error
+ timeout, err = caddy.ParseDuration(timeoutStr)
if err != nil {
- return nil, h.Errf("invalid dns_ttl duration %s: %v", ttlStr, err)
- }
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
- }
- if acmeIssuer.Challenges == nil {
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
+ return nil, h.Errf("invalid propagation_timeout duration %s: %v", timeoutStr, err)
}
- if acmeIssuer.Challenges.DNS == nil {
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
- }
- acmeIssuer.Challenges.DNS.TTL = caddy.Duration(ttl)
+ }
+ if acmeIssuer == nil {
+ acmeIssuer = new(caddytls.ACMEIssuer)
+ }
+ if acmeIssuer.Challenges == nil {
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
+ }
+ if acmeIssuer.Challenges.DNS == nil {
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
+ }
+ acmeIssuer.Challenges.DNS.PropagationTimeout = caddy.Duration(timeout)
- case "dns_challenge_override_domain":
- arg := h.RemainingArgs()
- if len(arg) != 1 {
- return nil, h.ArgErr()
- }
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
- }
- if acmeIssuer.Challenges == nil {
- acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
- }
- if acmeIssuer.Challenges.DNS == nil {
- acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
- }
- acmeIssuer.Challenges.DNS.OverrideDomain = arg[0]
+ case "dns_ttl":
+ arg := h.RemainingArgs()
+ if len(arg) != 1 {
+ return nil, h.ArgErr()
+ }
+ ttlStr := arg[0]
+ ttl, err := caddy.ParseDuration(ttlStr)
+ if err != nil {
+ return nil, h.Errf("invalid dns_ttl duration %s: %v", ttlStr, err)
+ }
+ if acmeIssuer == nil {
+ acmeIssuer = new(caddytls.ACMEIssuer)
+ }
+ if acmeIssuer.Challenges == nil {
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
+ }
+ if acmeIssuer.Challenges.DNS == nil {
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
+ }
+ acmeIssuer.Challenges.DNS.TTL = caddy.Duration(ttl)
- case "ca_root":
- arg := h.RemainingArgs()
- if len(arg) != 1 {
- return nil, h.ArgErr()
- }
- if acmeIssuer == nil {
- acmeIssuer = new(caddytls.ACMEIssuer)
- }
- acmeIssuer.TrustedRootsPEMFiles = append(acmeIssuer.TrustedRootsPEMFiles, arg[0])
+ case "dns_challenge_override_domain":
+ arg := h.RemainingArgs()
+ if len(arg) != 1 {
+ return nil, h.ArgErr()
+ }
+ if acmeIssuer == nil {
+ acmeIssuer = new(caddytls.ACMEIssuer)
+ }
+ if acmeIssuer.Challenges == nil {
+ acmeIssuer.Challenges = new(caddytls.ChallengesConfig)
+ }
+ if acmeIssuer.Challenges.DNS == nil {
+ acmeIssuer.Challenges.DNS = new(caddytls.DNSChallengeConfig)
+ }
+ acmeIssuer.Challenges.DNS.OverrideDomain = arg[0]
- case "on_demand":
- if h.NextArg() {
- return nil, h.ArgErr()
- }
- onDemand = true
+ case "ca_root":
+ arg := h.RemainingArgs()
+ if len(arg) != 1 {
+ return nil, h.ArgErr()
+ }
+ if acmeIssuer == nil {
+ acmeIssuer = new(caddytls.ACMEIssuer)
+ }
+ acmeIssuer.TrustedRootsPEMFiles = append(acmeIssuer.TrustedRootsPEMFiles, arg[0])
- case "reuse_private_keys":
- if h.NextArg() {
- return nil, h.ArgErr()
- }
- reusePrivateKeys = true
+ case "on_demand":
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ onDemand = true
- case "insecure_secrets_log":
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- cp.InsecureSecretsLog = h.Val()
+ case "reuse_private_keys":
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ reusePrivateKeys = true
- default:
- return nil, h.Errf("unknown subdirective: %s", h.Val())
+ case "insecure_secrets_log":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
}
- }
+ cp.InsecureSecretsLog = h.Val()
- // a naked tls directive is not allowed
- if len(firstLine) == 0 && !hasBlock {
- return nil, h.ArgErr()
+ default:
+ return nil, h.Errf("unknown subdirective: %s", h.Val())
}
}
+ // a naked tls directive is not allowed
+ if len(firstLine) == 0 && !hasBlock {
+ return nil, h.ArgErr()
+ }
+
// begin building the final config values
configVals := []ConfigValue{}
@@ -646,10 +643,7 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
//
// root [<matcher>] <path>
func parseRoot(h Helper) ([]ConfigValue, error) {
- // consume directive name
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
+ h.Next() // consume directive name
// count the tokens to determine what to do
argsCount := h.CountRemainingArgs()
@@ -673,11 +667,8 @@ func parseRoot(h Helper) ([]ConfigValue, error) {
if err != nil {
return nil, err
}
+ h.Next() // consume directive name again, matcher parsing does a reset
- // consume directive name, again, because extracting matcher does a reset
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
// advance to the root path
if !h.NextArg() {
return nil, h.ArgErr()
@@ -690,17 +681,14 @@ func parseRoot(h Helper) ([]ConfigValue, error) {
//
// fs <filesystem>
func parseFilesystem(h Helper) (caddyhttp.MiddlewareHandler, error) {
- var name string
- for h.Next() {
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- name = h.Val()
- if h.NextArg() {
- return nil, h.ArgErr()
- }
+ h.Next() // consume directive name
+ if !h.NextArg() {
+ return nil, h.ArgErr()
}
- return caddyhttp.VarsMiddleware{"fs": name}, nil
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ return caddyhttp.VarsMiddleware{"fs": h.Val()}, nil
}
// parseVars parses the vars directive. See its UnmarshalCaddyfile method for syntax.
@@ -720,10 +708,7 @@ func parseVars(h Helper) (caddyhttp.MiddlewareHandler, error) {
// respond with HTTP 200 and no Location header; redirect is performed
// with JS and a meta tag).
func parseRedir(h Helper) (caddyhttp.MiddlewareHandler, error) {
- if !h.Next() {
- return nil, h.ArgErr()
- }
-
+ h.Next() // consume directive name
if !h.NextArg() {
return nil, h.ArgErr()
}
@@ -739,8 +724,10 @@ func parseRedir(h Helper) (caddyhttp.MiddlewareHandler, error) {
switch code {
case "permanent":
code = "301"
+
case "temporary", "":
code = "302"
+
case "html":
// Script tag comes first since that will better imitate a redirect in the browser's
// history, but the meta tag is a fallback for most non-JS clients.
@@ -758,6 +745,7 @@ func parseRedir(h Helper) (caddyhttp.MiddlewareHandler, error) {
body = fmt.Sprintf(metaRedir, safeTo, safeTo, safeTo, safeTo)
hdr = http.Header{"Content-Type": []string{"text/html; charset=utf-8"}}
code = "200" // don't redirect non-browser clients
+
default:
// Allow placeholders for the code
if strings.HasPrefix(code, "{") {
@@ -796,10 +784,7 @@ func parseRedir(h Helper) (caddyhttp.MiddlewareHandler, error) {
func parseRespond(h Helper) (caddyhttp.MiddlewareHandler, error) {
sr := new(caddyhttp.StaticResponse)
err := sr.UnmarshalCaddyfile(h.Dispenser)
- if err != nil {
- return nil, err
- }
- return sr, nil
+ return sr, err
}
// parseAbort parses the abort directive.
@@ -815,10 +800,7 @@ func parseAbort(h Helper) (caddyhttp.MiddlewareHandler, error) {
func parseError(h Helper) (caddyhttp.MiddlewareHandler, error) {
se := new(caddyhttp.StaticError)
err := se.UnmarshalCaddyfile(h.Dispenser)
- if err != nil {
- return nil, err
- }
- return se, nil
+ return se, err
}
// parseRoute parses the route directive.
@@ -844,11 +826,11 @@ func parseHandle(h Helper) (caddyhttp.MiddlewareHandler, error) {
}
func parseHandleErrors(h Helper) ([]ConfigValue, error) {
- h.Next()
- args := h.RemainingArgs()
+ h.Next() // consume directive name
+
expression := ""
+ args := h.RemainingArgs()
if len(args) > 0 {
- expression = ""
codes := []string{}
for _, val := range args {
if len(val) != 3 {
@@ -951,184 +933,185 @@ func parseLog(h Helper) ([]ConfigValue, error) {
// level. The parseAsGlobalOption parameter is used to distinguish any differing logic
// between the two.
func parseLogHelper(h Helper, globalLogNames map[string]struct{}) ([]ConfigValue, error) {
+ h.Next() // consume option name
+
// When the globalLogNames parameter is passed in, we make
// modifications to the parsing behavior.
parseAsGlobalOption := globalLogNames != nil
var configValues []ConfigValue
- for h.Next() {
- // Logic below expects that a name is always present when a
- // global option is being parsed; or an optional override
- // is supported for access logs.
- var logName string
- if parseAsGlobalOption {
- if h.NextArg() {
- logName = h.Val()
+ // Logic below expects that a name is always present when a
+ // global option is being parsed; or an optional override
+ // is supported for access logs.
+ var logName string
- // Only a single argument is supported.
- if h.NextArg() {
- return nil, h.ArgErr()
- }
- } else {
- // If there is no log name specified, we
- // reference the default logger. See the
- // setupNewDefault function in the logging
- // package for where this is configured.
- logName = caddy.DefaultLoggerName
- }
+ if parseAsGlobalOption {
+ if h.NextArg() {
+ logName = h.Val()
- // Verify this name is unused.
- _, used := globalLogNames[logName]
- if used {
- return nil, h.Err("duplicate global log option for: " + logName)
+ // Only a single argument is supported.
+ if h.NextArg() {
+ return nil, h.ArgErr()
}
- globalLogNames[logName] = struct{}{}
} else {
- // An optional override of the logger name can be provided;
- // otherwise a default will be used, like "log0", "log1", etc.
- if h.NextArg() {
- logName = h.Val()
+ // If there is no log name specified, we
+ // reference the default logger. See the
+ // setupNewDefault function in the logging
+ // package for where this is configured.
+ logName = caddy.DefaultLoggerName
+ }
- // Only a single argument is supported.
- if h.NextArg() {
- return nil, h.ArgErr()
- }
- }
+ // Verify this name is unused.
+ _, used := globalLogNames[logName]
+ if used {
+ return nil, h.Err("duplicate global log option for: " + logName)
}
+ globalLogNames[logName] = struct{}{}
+ } else {
+ // An optional override of the logger name can be provided;
+ // otherwise a default will be used, like "log0", "log1", etc.
+ if h.NextArg() {
+ logName = h.Val()
- cl := new(caddy.CustomLog)
+ // Only a single argument is supported.
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ }
+ }
- // allow overriding the current site block's hostnames for this logger;
- // this is useful for setting up loggers per subdomain in a site block
- // with a wildcard domain
- customHostnames := []string{}
+ cl := new(caddy.CustomLog)
- for h.NextBlock(0) {
- switch h.Val() {
- case "hostnames":
- if parseAsGlobalOption {
- return nil, h.Err("hostnames is not allowed in the log global options")
- }
- args := h.RemainingArgs()
- if len(args) == 0 {
- return nil, h.ArgErr()
- }
- customHostnames = append(customHostnames, args...)
+ // allow overriding the current site block's hostnames for this logger;
+ // this is useful for setting up loggers per subdomain in a site block
+ // with a wildcard domain
+ customHostnames := []string{}
- case "output":
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- moduleName := h.Val()
-
- // can't use the usual caddyfile.Unmarshaler flow with the
- // standard writers because they are in the caddy package
- // (because they are the default) and implementing that
- // interface there would unfortunately create circular import
- var wo caddy.WriterOpener
- switch moduleName {
- case "stdout":
- wo = caddy.StdoutWriter{}
- case "stderr":
- wo = caddy.StderrWriter{}
- case "discard":
- wo = caddy.DiscardWriter{}
- default:
- modID := "caddy.logging.writers." + moduleName
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
- if err != nil {
- return nil, err
- }
- var ok bool
- wo, ok = unm.(caddy.WriterOpener)
- if !ok {
- return nil, h.Errf("module %s (%T) is not a WriterOpener", modID, unm)
- }
- }
- cl.WriterRaw = caddyconfig.JSONModuleObject(wo, "output", moduleName, h.warnings)
+ for h.NextBlock(0) {
+ switch h.Val() {
+ case "hostnames":
+ if parseAsGlobalOption {
+ return nil, h.Err("hostnames is not allowed in the log global options")
+ }
+ args := h.RemainingArgs()
+ if len(args) == 0 {
+ return nil, h.ArgErr()
+ }
+ customHostnames = append(customHostnames, args...)
- case "format":
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- moduleName := h.Val()
- moduleID := "caddy.logging.encoders." + moduleName
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, moduleID)
+ case "output":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ moduleName := h.Val()
+
+ // can't use the usual caddyfile.Unmarshaler flow with the
+ // standard writers because they are in the caddy package
+ // (because they are the default) and implementing that
+ // interface there would unfortunately create circular import
+ var wo caddy.WriterOpener
+ switch moduleName {
+ case "stdout":
+ wo = caddy.StdoutWriter{}
+ case "stderr":
+ wo = caddy.StderrWriter{}
+ case "discard":
+ wo = caddy.DiscardWriter{}
+ default:
+ modID := "caddy.logging.writers." + moduleName
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
if err != nil {
return nil, err
}
- enc, ok := unm.(zapcore.Encoder)
+ var ok bool
+ wo, ok = unm.(caddy.WriterOpener)
if !ok {
- return nil, h.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
+ return nil, h.Errf("module %s (%T) is not a WriterOpener", modID, unm)
}
- cl.EncoderRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, h.warnings)
+ }
+ cl.WriterRaw = caddyconfig.JSONModuleObject(wo, "output", moduleName, h.warnings)
- case "level":
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- cl.Level = h.Val()
- if h.NextArg() {
- return nil, h.ArgErr()
- }
+ case "format":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ moduleName := h.Val()
+ moduleID := "caddy.logging.encoders." + moduleName
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, moduleID)
+ if err != nil {
+ return nil, err
+ }
+ enc, ok := unm.(zapcore.Encoder)
+ if !ok {
+ return nil, h.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
+ }
+ cl.EncoderRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, h.warnings)
- case "include":
- if !parseAsGlobalOption {
- return nil, h.Err("include is not allowed in the log directive")
- }
- for h.NextArg() {
- cl.Include = append(cl.Include, h.Val())
- }
+ case "level":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ cl.Level = h.Val()
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
- case "exclude":
- if !parseAsGlobalOption {
- return nil, h.Err("exclude is not allowed in the log directive")
- }
- for h.NextArg() {
- cl.Exclude = append(cl.Exclude, h.Val())
- }
+ case "include":
+ if !parseAsGlobalOption {
+ return nil, h.Err("include is not allowed in the log directive")
+ }
+ for h.NextArg() {
+ cl.Include = append(cl.Include, h.Val())
+ }
- default:
- return nil, h.Errf("unrecognized subdirective: %s", h.Val())
+ case "exclude":
+ if !parseAsGlobalOption {
+ return nil, h.Err("exclude is not allowed in the log directive")
+ }
+ for h.NextArg() {
+ cl.Exclude = append(cl.Exclude, h.Val())
}
+
+ default:
+ return nil, h.Errf("unrecognized subdirective: %s", h.Val())
}
+ }
- var val namedCustomLog
- val.hostnames = customHostnames
+ var val namedCustomLog
+ val.hostnames = customHostnames
- isEmptyConfig := reflect.DeepEqual(cl, new(caddy.CustomLog))
+ isEmptyConfig := reflect.DeepEqual(cl, new(caddy.CustomLog))
- // Skip handling of empty logging configs
+ // Skip handling of empty logging configs
- if parseAsGlobalOption {
- // Use indicated name for global log options
+ if parseAsGlobalOption {
+ // Use indicated name for global log options
+ val.name = logName
+ } else {
+ if logName != "" {
val.name = logName
- } else {
- if logName != "" {
- val.name = logName
- } else if !isEmptyConfig {
- // Construct a log name for server log streams
- logCounter, ok := h.State["logCounter"].(int)
- if !ok {
- logCounter = 0
- }
- val.name = fmt.Sprintf("log%d", logCounter)
- logCounter++
- h.State["logCounter"] = logCounter
- }
- if val.name != "" {
- cl.Include = []string{"http.log.access." + val.name}
+ } else if !isEmptyConfig {
+ // Construct a log name for server log streams
+ logCounter, ok := h.State["logCounter"].(int)
+ if !ok {
+ logCounter = 0
}
+ val.name = fmt.Sprintf("log%d", logCounter)
+ logCounter++
+ h.State["logCounter"] = logCounter
}
- if !isEmptyConfig {
- val.log = cl
+ if val.name != "" {
+ cl.Include = []string{"http.log.access." + val.name}
}
- configValues = append(configValues, ConfigValue{
- Class: "custom_log",
- Value: val,
- })
}
+ if !isEmptyConfig {
+ val.log = cl
+ }
+ configValues = append(configValues, ConfigValue{
+ Class: "custom_log",
+ Value: val,
+ })
return configValues, nil
}
@@ -1136,10 +1119,9 @@ func parseLogHelper(h Helper, globalLogNames map[string]struct{}) ([]ConfigValue
//
// skip_log [<matcher>]
func parseSkipLog(h Helper) (caddyhttp.MiddlewareHandler, error) {
- for h.Next() {
- if h.NextArg() {
- return nil, h.ArgErr()
- }
+ h.Next() // consume directive name
+ if h.NextArg() {
+ return nil, h.ArgErr()
}
return caddyhttp.VarsMiddleware{"skip_log": true}, nil
}
diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go
index 58da2bd79..6e5241c7f 100644
--- a/caddyconfig/httpcaddyfile/directives.go
+++ b/caddyconfig/httpcaddyfile/directives.go
@@ -271,12 +271,6 @@ func (h Helper) GroupRoutes(vals []ConfigValue) {
}
}
-// NewBindAddresses returns config values relevant to adding
-// listener bind addresses to the config.
-func (h Helper) NewBindAddresses(addrs []string) []ConfigValue {
- return []ConfigValue{{Class: "bind", Value: addrs}}
-}
-
// WithDispenser returns a new instance based on d. All others Helper
// fields are copied, so typically maps are shared with this new instance.
func (h Helper) WithDispenser(d *caddyfile.Dispenser) Helper {
diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go
index 066df3014..54e781119 100644
--- a/caddyconfig/httpcaddyfile/httptype.go
+++ b/caddyconfig/httpcaddyfile/httptype.go
@@ -1381,68 +1381,73 @@ func (st *ServerType) compileEncodedMatcherSets(sblock serverBlock) ([]caddy.Mod
}
func parseMatcherDefinitions(d *caddyfile.Dispenser, matchers map[string]caddy.ModuleMap) error {
- for d.Next() {
- // this is the "name" for "named matchers"
- definitionName := d.Val()
+ d.Next() // advance to the first token
- if _, ok := matchers[definitionName]; ok {
- return fmt.Errorf("matcher is defined more than once: %s", definitionName)
+ // this is the "name" for "named matchers"
+ definitionName := d.Val()
+
+ if _, ok := matchers[definitionName]; ok {
+ return fmt.Errorf("matcher is defined more than once: %s", definitionName)
+ }
+ matchers[definitionName] = make(caddy.ModuleMap)
+
+ // given a matcher name and the tokens following it, parse
+ // the tokens as a matcher module and record it
+ makeMatcher := func(matcherName string, tokens []caddyfile.Token) error {
+ mod, err := caddy.GetModule("http.matchers." + matcherName)
+ if err != nil {
+ return fmt.Errorf("getting matcher module '%s': %v", matcherName, err)
}
- matchers[definitionName] = make(caddy.ModuleMap)
+ unm, ok := mod.New().(caddyfile.Unmarshaler)
+ if !ok {
+ return fmt.Errorf("matcher module '%s' is not a Caddyfile unmarshaler", matcherName)
+ }
+ err = unm.UnmarshalCaddyfile(caddyfile.NewDispenser(tokens))
+ if err != nil {
+ return err
+ }
+ rm, ok := unm.(caddyhttp.RequestMatcher)
+ if !ok {
+ return fmt.Errorf("matcher module '%s' is not a request matcher", matcherName)
+ }
+ matchers[definitionName][matcherName] = caddyconfig.JSON(rm, nil)
+ return nil
+ }
- // given a matcher name and the tokens following it, parse
- // the tokens as a matcher module and record it
- makeMatcher := func(matcherName string, tokens []caddyfile.Token) error {
- mod, err := caddy.GetModule("http.matchers." + matcherName)
- if err != nil {
- return fmt.Errorf("getting matcher module '%s': %v", matcherName, err)
- }
- unm, ok := mod.New().(caddyfile.Unmarshaler)
- if !ok {
- return fmt.Errorf("matcher module '%s' is not a Caddyfile unmarshaler", matcherName)
- }
- err = unm.UnmarshalCaddyfile(caddyfile.NewDispenser(tokens))
+ // if the next token is quoted, we can assume it's not a matcher name
+ // and that it's probably an 'expression' matcher
+ if d.NextArg() {
+ if d.Token().Quoted() {
+ // since it was missing the matcher name, we insert a token
+ // in front of the expression token itself
+ err := makeMatcher("expression", []caddyfile.Token{
+ {Text: "expression", File: d.File(), Line: d.Line()},
+ d.Token(),
+ })
if err != nil {
return err
}
- rm, ok := unm.(caddyhttp.RequestMatcher)
- if !ok {
- return fmt.Errorf("matcher module '%s' is not a request matcher", matcherName)
- }
- matchers[definitionName][matcherName] = caddyconfig.JSON(rm, nil)
return nil
}
- // if the next token is quoted, we can assume it's not a matcher name
- // and that it's probably an 'expression' matcher
- if d.NextArg() {
- if d.Token().Quoted() {
- err := makeMatcher("expression", []caddyfile.Token{d.Token()})
- if err != nil {
- return err
- }
- continue
- }
-
- // if it wasn't quoted, then we need to rewind after calling
- // d.NextArg() so the below properly grabs the matcher name
- d.Prev()
- }
+ // if it wasn't quoted, then we need to rewind after calling
+ // d.NextArg() so the below properly grabs the matcher name
+ d.Prev()
+ }
- // in case there are multiple instances of the same matcher, concatenate
- // their tokens (we expect that UnmarshalCaddyfile should be able to
- // handle more than one segment); otherwise, we'd overwrite other
- // instances of the matcher in this set
- tokensByMatcherName := make(map[string][]caddyfile.Token)
- for nesting := d.Nesting(); d.NextArg() || d.NextBlock(nesting); {
- matcherName := d.Val()
- tokensByMatcherName[matcherName] = append(tokensByMatcherName[matcherName], d.NextSegment()...)
- }
- for matcherName, tokens := range tokensByMatcherName {
- err := makeMatcher(matcherName, tokens)
- if err != nil {
- return err
- }
+ // in case there are multiple instances of the same matcher, concatenate
+ // their tokens (we expect that UnmarshalCaddyfile should be able to
+ // handle more than one segment); otherwise, we'd overwrite other
+ // instances of the matcher in this set
+ tokensByMatcherName := make(map[string][]caddyfile.Token)
+ for nesting := d.Nesting(); d.NextArg() || d.NextBlock(nesting); {
+ matcherName := d.Val()
+ tokensByMatcherName[matcherName] = append(tokensByMatcherName[matcherName], d.NextSegment()...)
+ }
+ for matcherName, tokens := range tokensByMatcherName {
+ err := makeMatcher(matcherName, tokens)
+ if err != nil {
+ return err
}
}
return nil
diff --git a/caddyconfig/httpcaddyfile/options.go b/caddyconfig/httpcaddyfile/options.go
index ba1896b6b..fa447f8dc 100644
--- a/caddyconfig/httpcaddyfile/options.go
+++ b/caddyconfig/httpcaddyfile/options.go
@@ -62,105 +62,103 @@ func init() {
func parseOptTrue(d *caddyfile.Dispenser, _ any) (any, error) { return true, nil }
func parseOptHTTPPort(d *caddyfile.Dispenser, _ any) (any, error) {
+ d.Next() // consume option name
var httpPort int
- for d.Next() {
- var httpPortStr string
- if !d.AllArgs(&httpPortStr) {
- return 0, d.ArgErr()
- }
- var err error
- httpPort, err = strconv.Atoi(httpPortStr)
- if err != nil {
- return 0, d.Errf("converting port '%s' to integer value: %v", httpPortStr, err)
- }
+ var httpPortStr string
+ if !d.AllArgs(&httpPortStr) {
+ return 0, d.ArgErr()
+ }
+ var err error
+ httpPort, err = strconv.Atoi(httpPortStr)
+ if err != nil {
+ return 0, d.Errf("converting port '%s' to integer value: %v", httpPortStr, err)
}
return httpPort, nil
}
func parseOptHTTPSPort(d *caddyfile.Dispenser, _ any) (any, error) {
+ d.Next() // consume option name
var httpsPort int
- for d.Next() {
- var httpsPortStr string
- if !d.AllArgs(&httpsPortStr) {
- return 0, d.ArgErr()
- }
- var err error
- httpsPort, err = strconv.Atoi(httpsPortStr)
- if err != nil {
- return 0, d.Errf("converting port '%s' to integer value: %v", httpsPortStr, err)
- }
+ var httpsPortStr string
+ if !d.AllArgs(&httpsPortStr) {
+ return 0, d.ArgErr()
+ }
+ var err error
+ httpsPort, err = strconv.Atoi(httpsPortStr)
+ if err != nil {
+ return 0, d.Errf("converting port '%s' to integer value: %v", httpsPortStr, err)
}
return httpsPort, nil
}
func parseOptOrder(d *caddyfile.Dispenser, _ any) (any, error) {
- newOrder := directiveOrder
+ d.Next() // consume option name
- for d.Next() {
- // get directive name
- if !d.Next() {
- return nil, d.ArgErr()
- }
- dirName := d.Val()
- if _, ok := registeredDirectives[dirName]; !ok {
- return nil, d.Errf("%s is not a registered directive", dirName)
- }
+ // get directive name
+ if !d.Next() {
+ return nil, d.ArgErr()
+ }
+ dirName := d.Val()
+ if _, ok := registeredDirectives[dirName]; !ok {
+ return nil, d.Errf("%s is not a registered directive", dirName)
+ }
- // get positional token
- if !d.Next() {
- return nil, d.ArgErr()
- }
- pos := d.Val()
+ // get positional token
+ if !d.Next() {
+ return nil, d.ArgErr()
+ }
+ pos := d.Val()
- // if directive exists, first remove it
- for i, d := range newOrder {
- if d == dirName {
- newOrder = append(newOrder[:i], newOrder[i+1:]...)
- break
- }
- }
+ newOrder := directiveOrder
- // act on the positional
- switch pos {
- case "first":
- newOrder = append([]string{dirName}, newOrder...)
- if d.NextArg() {
- return nil, d.ArgErr()
- }
- directiveOrder = newOrder
- return newOrder, nil
- case "last":
- newOrder = append(newOrder, dirName)
- if d.NextArg() {
- return nil, d.ArgErr()
- }
- directiveOrder = newOrder
- return newOrder, nil
- case "before":
- case "after":
- default:
- return nil, d.Errf("unknown positional '%s'", pos)
+ // if directive exists, first remove it
+ for i, d := range newOrder {
+ if d == dirName {
+ newOrder = append(newOrder[:i], newOrder[i+1:]...)
+ break
}
+ }
- // get name of other directive
- if !d.NextArg() {
+ // act on the positional
+ switch pos {
+ case "first":
+ newOrder = append([]string{dirName}, newOrder...)
+ if d.NextArg() {
return nil, d.ArgErr()
}
- otherDir := d.Val()
+ directiveOrder = newOrder
+ return newOrder, nil
+ case "last":
+ newOrder = append(newOrder, dirName)
if d.NextArg() {
return nil, d.ArgErr()
}
+ directiveOrder = newOrder
+ return newOrder, nil
+ case "before":
+ case "after":
+ default:
+ return nil, d.Errf("unknown positional '%s'", pos)
+ }
+
+ // get name of other directive
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ otherDir := d.Val()
+ if d.NextArg() {
+ return nil, d.ArgErr()
+ }
- // insert directive into proper position
- for i, d := range newOrder {
- if d == otherDir {
- if pos == "before" {
- newOrder = append(newOrder[:i], append([]string{dirName}, newOrder[i:]...)...)
- } else if pos == "after" {
- newOrder = append(newOrder[:i+1], append([]string{dirName}, newOrder[i+1:]...)...)
- }
- break
+ // insert directive into proper position
+ for i, d := range newOrder {
+ if d == otherDir {
+ if pos == "before" {
+ newOrder = append(newOrder[:i], append([]string{dirName}, newOrder[i:]...)...)
+ } else if pos == "after" {
+ newOrder = append(newOrder[:i+1], append([]string{dirName}, newOrder[i+1:]...)...)
}
+ break
}
}
@@ -223,57 +221,58 @@ func parseOptACMEDNS(d *caddyfile.Dispenser, _ any) (any, error) {
func parseOptACMEEAB(d *caddyfile.Dispenser, _ any) (any, error) {
eab := new(acme.EAB)
- for d.Next() {
- if d.NextArg() {
- return nil, d.ArgErr()
- }
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "key_id":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- eab.KeyID = d.Val()
-
- case "mac_key":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- eab.MACKey = d.Val()
-
- default:
- return nil, d.Errf("unrecognized parameter '%s'", d.Val())
+ d.Next() // consume option name
+ if d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "key_id":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ eab.KeyID = d.Val()
+
+ case "mac_key":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
}
+ eab.MACKey = d.Val()
+
+ default:
+ return nil, d.Errf("unrecognized parameter '%s'", d.Val())
}
}
return eab, nil
}
func parseOptCertIssuer(d *caddyfile.Dispenser, existing any) (any, error) {
+ d.Next() // consume option name
+
var issuers []certmagic.Issuer
if existing != nil {
issuers = existing.([]certmagic.Issuer)
}
- for d.Next() { // consume option name
- if !d.Next() { // get issuer module name
- return nil, d.ArgErr()
- }
- modID := "tls.issuance." + d.Val()
- unm, err := caddyfile.UnmarshalModule(d, modID)
- if err != nil {
- return nil, err
- }
- iss, ok := unm.(certmagic.Issuer)
- if !ok {
- return nil, d.Errf("module %s (%T) is not a certmagic.Issuer", modID, unm)
- }
- issuers = append(issuers, iss)
+
+ // get issuer module name
+ if !d.Next() {
+ return nil, d.ArgErr()
+ }
+ modID := "tls.issuance." + d.Val()
+ unm, err := caddyfile.UnmarshalModule(d, modID)
+ if err != nil {
+ return nil, err
+ }
+ iss, ok := unm.(certmagic.Issuer)
+ if !ok {
+ return nil, d.Errf("module %s (%T) is not a certmagic.Issuer", modID, unm)
}
+ issuers = append(issuers, iss)
return issuers, nil
}
func parseOptSingleString(d *caddyfile.Dispenser, _ any) (any, error) {
- d.Next() // consume parameter name
+ d.Next() // consume option name
if !d.Next() {
return "", d.ArgErr()
}
@@ -285,7 +284,7 @@ func parseOptSingleString(d *caddyfile.Dispenser, _ any) (any, error) {
}
func parseOptStringList(d *caddyfile.Dispenser, _ any) (any, error) {
- d.Next() // consume parameter name
+ d.Next() // consume option name
val := d.RemainingArgs()
if len(val) == 0 {
return "", d.ArgErr()
@@ -294,33 +293,33 @@ func parseOptStringList(d *caddyfile.Dispenser, _ any) (any, error) {
}
func parseOptAdmin(d *caddyfile.Dispenser, _ any) (any, error) {
+ d.Next() // consume option name
+
adminCfg := new(caddy.AdminConfig)
- for d.Next() {
- if d.NextArg() {
- listenAddress := d.Val()
- if listenAddress == "off" {
- adminCfg.Disabled = true
- if d.Next() { // Do not accept any remaining options including block
- return nil, d.Err("No more option is allowed after turning off admin config")
- }
- } else {
- adminCfg.Listen = listenAddress
- if d.NextArg() { // At most 1 arg is allowed
- return nil, d.ArgErr()
- }
+ if d.NextArg() {
+ listenAddress := d.Val()
+ if listenAddress == "off" {
+ adminCfg.Disabled = true
+ if d.Next() { // Do not accept any remaining options including block
+ return nil, d.Err("No more option is allowed after turning off admin config")
+ }
+ } else {
+ adminCfg.Listen = listenAddress
+ if d.NextArg() { // At most 1 arg is allowed
+ return nil, d.ArgErr()
}
}
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "enforce_origin":
- adminCfg.EnforceOrigin = true
+ }
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "enforce_origin":
+ adminCfg.EnforceOrigin = true
- case "origins":
- adminCfg.Origins = d.RemainingArgs()
+ case "origins":
+ adminCfg.Origins = d.RemainingArgs()
- default:
- return nil, d.Errf("unrecognized parameter '%s'", d.Val())
- }
+ default:
+ return nil, d.Errf("unrecognized parameter '%s'", d.Val())
}
}
if adminCfg.Listen == "" && !adminCfg.Disabled {
@@ -330,57 +329,57 @@ func parseOptAdmin(d *caddyfile.Dispenser, _ any) (any, error) {
}
func parseOptOnDemand(d *caddyfile.Dispenser, _ any) (any, error) {
+ d.Next() // consume option name
+ if d.NextArg() {
+ return nil, d.ArgErr()
+ }
+
var ond *caddytls.OnDemandConfig
- for d.Next() {
- if d.NextArg() {
- return nil, d.ArgErr()
- }
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "ask":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- if ond == nil {
- ond = new(caddytls.OnDemandConfig)
- }
- ond.Ask = d.Val()
-
- case "interval":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return nil, err
- }
- if ond == nil {
- ond = new(caddytls.OnDemandConfig)
- }
- if ond.RateLimit == nil {
- ond.RateLimit = new(caddytls.RateLimit)
- }
- ond.RateLimit.Interval = caddy.Duration(dur)
-
- case "burst":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- burst, err := strconv.Atoi(d.Val())
- if err != nil {
- return nil, err
- }
- if ond == nil {
- ond = new(caddytls.OnDemandConfig)
- }
- if ond.RateLimit == nil {
- ond.RateLimit = new(caddytls.RateLimit)
- }
- ond.RateLimit.Burst = burst
-
- default:
- return nil, d.Errf("unrecognized parameter '%s'", d.Val())
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "ask":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ if ond == nil {
+ ond = new(caddytls.OnDemandConfig)
+ }
+ ond.Ask = d.Val()
+
+ case "interval":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return nil, err
}
+ if ond == nil {
+ ond = new(caddytls.OnDemandConfig)
+ }
+ if ond.RateLimit == nil {
+ ond.RateLimit = new(caddytls.RateLimit)
+ }
+ ond.RateLimit.Interval = caddy.Duration(dur)
+
+ case "burst":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ burst, err := strconv.Atoi(d.Val())
+ if err != nil {
+ return nil, err
+ }
+ if ond == nil {
+ ond = new(caddytls.OnDemandConfig)
+ }
+ if ond.RateLimit == nil {
+ ond.RateLimit = new(caddytls.RateLimit)
+ }
+ ond.RateLimit.Burst = burst
+
+ default:
+ return nil, d.Errf("unrecognized parameter '%s'", d.Val())
}
}
if ond == nil {
@@ -390,7 +389,7 @@ func parseOptOnDemand(d *caddyfile.Dispenser, _ any) (any, error) {
}
func parseOptPersistConfig(d *caddyfile.Dispenser, _ any) (any, error) {
- d.Next() // consume parameter name
+ d.Next() // consume option name
if !d.Next() {
return "", d.ArgErr()
}
@@ -405,7 +404,7 @@ func parseOptPersistConfig(d *caddyfile.Dispenser, _ any) (any, error) {
}
func parseOptAutoHTTPS(d *caddyfile.Dispenser, _ any) (any, error) {
- d.Next() // consume parameter name
+ d.Next() // consume option name
if !d.Next() {
return "", d.ArgErr()
}
diff --git a/caddyconfig/httpcaddyfile/pkiapp.go b/caddyconfig/httpcaddyfile/pkiapp.go
index b5c682187..c57263baf 100644
--- a/caddyconfig/httpcaddyfile/pkiapp.go
+++ b/caddyconfig/httpcaddyfile/pkiapp.go
@@ -48,124 +48,124 @@ func init() {
//
// When the CA ID is unspecified, 'local' is assumed.
func parsePKIApp(d *caddyfile.Dispenser, existingVal any) (any, error) {
- pki := &caddypki.PKI{CAs: make(map[string]*caddypki.CA)}
+ d.Next() // consume app name
- for d.Next() {
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "ca":
- pkiCa := new(caddypki.CA)
+ pki := &caddypki.PKI{
+ CAs: make(map[string]*caddypki.CA),
+ }
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "ca":
+ pkiCa := new(caddypki.CA)
+ if d.NextArg() {
+ pkiCa.ID = d.Val()
if d.NextArg() {
- pkiCa.ID = d.Val()
- if d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ }
+ if pkiCa.ID == "" {
+ pkiCa.ID = caddypki.DefaultCAID
+ }
+
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
+ switch d.Val() {
+ case "name":
+ if !d.NextArg() {
return nil, d.ArgErr()
}
- }
- if pkiCa.ID == "" {
- pkiCa.ID = caddypki.DefaultCAID
- }
+ pkiCa.Name = d.Val()
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "name":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- pkiCa.Name = d.Val()
+ case "root_cn":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ pkiCa.RootCommonName = d.Val()
- case "root_cn":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- pkiCa.RootCommonName = d.Val()
+ case "intermediate_cn":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ pkiCa.IntermediateCommonName = d.Val()
- case "intermediate_cn":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- pkiCa.IntermediateCommonName = d.Val()
+ case "intermediate_lifetime":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return nil, err
+ }
+ pkiCa.IntermediateLifetime = caddy.Duration(dur)
- case "intermediate_lifetime":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return nil, err
- }
- pkiCa.IntermediateLifetime = caddy.Duration(dur)
+ case "root":
+ if pkiCa.Root == nil {
+ pkiCa.Root = new(caddypki.KeyPair)
+ }
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
+ switch d.Val() {
+ case "cert":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ pkiCa.Root.Certificate = d.Val()
- case "root":
- if pkiCa.Root == nil {
- pkiCa.Root = new(caddypki.KeyPair)
- }
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "cert":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- pkiCa.Root.Certificate = d.Val()
-
- case "key":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- pkiCa.Root.PrivateKey = d.Val()
-
- case "format":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- pkiCa.Root.Format = d.Val()
-
- default:
- return nil, d.Errf("unrecognized pki ca root option '%s'", d.Val())
+ case "key":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
}
- }
+ pkiCa.Root.PrivateKey = d.Val()
- case "intermediate":
- if pkiCa.Intermediate == nil {
- pkiCa.Intermediate = new(caddypki.KeyPair)
- }
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "cert":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- pkiCa.Intermediate.Certificate = d.Val()
-
- case "key":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- pkiCa.Intermediate.PrivateKey = d.Val()
-
- case "format":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- pkiCa.Intermediate.Format = d.Val()
-
- default:
- return nil, d.Errf("unrecognized pki ca intermediate option '%s'", d.Val())
+ case "format":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
}
+ pkiCa.Root.Format = d.Val()
+
+ default:
+ return nil, d.Errf("unrecognized pki ca root option '%s'", d.Val())
}
+ }
- default:
- return nil, d.Errf("unrecognized pki ca option '%s'", d.Val())
+ case "intermediate":
+ if pkiCa.Intermediate == nil {
+ pkiCa.Intermediate = new(caddypki.KeyPair)
}
- }
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
+ switch d.Val() {
+ case "cert":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ pkiCa.Intermediate.Certificate = d.Val()
- pki.CAs[pkiCa.ID] = pkiCa
+ case "key":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ pkiCa.Intermediate.PrivateKey = d.Val()
- default:
- return nil, d.Errf("unrecognized pki option '%s'", d.Val())
+ case "format":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ pkiCa.Intermediate.Format = d.Val()
+
+ default:
+ return nil, d.Errf("unrecognized pki ca intermediate option '%s'", d.Val())
+ }
+ }
+
+ default:
+ return nil, d.Errf("unrecognized pki ca option '%s'", d.Val())
+ }
}
+
+ pki.CAs[pkiCa.ID] = pkiCa
+
+ default:
+ return nil, d.Errf("unrecognized pki option '%s'", d.Val())
}
}
-
return pki, nil
}
diff --git a/caddyconfig/httpcaddyfile/serveroptions.go b/caddyconfig/httpcaddyfile/serveroptions.go
index c131a6417..62902b964 100644
--- a/caddyconfig/httpcaddyfile/serveroptions.go
+++ b/caddyconfig/httpcaddyfile/serveroptions.go
@@ -53,235 +53,235 @@ type serverOptions struct {
}
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
+ d.Next() // consume option name
+
serverOpts := serverOptions{}
- for d.Next() {
+ if d.NextArg() {
+ serverOpts.ListenerAddress = d.Val()
if d.NextArg() {
- serverOpts.ListenerAddress = d.Val()
- if d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ }
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "name":
+ if serverOpts.ListenerAddress == "" {
+ return nil, d.Errf("cannot set a name for a server without a listener address")
+ }
+ if !d.NextArg() {
return nil, d.ArgErr()
}
- }
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "name":
- if serverOpts.ListenerAddress == "" {
- return nil, d.Errf("cannot set a name for a server without a listener address")
+ serverOpts.Name = d.Val()
+
+ case "listener_wrappers":
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
+ modID := "caddy.listeners." + d.Val()
+ unm, err := caddyfile.UnmarshalModule(d, modID)
+ if err != nil {
+ return nil, err
}
- if !d.NextArg() {
- return nil, d.ArgErr()
+ listenerWrapper, ok := unm.(caddy.ListenerWrapper)
+ if !ok {
+ return nil, fmt.Errorf("module %s (%T) is not a listener wrapper", modID, unm)
}
- serverOpts.Name = d.Val()
+ jsonListenerWrapper := caddyconfig.JSONModuleObject(
+ listenerWrapper,
+ "wrapper",
+ listenerWrapper.(caddy.Module).CaddyModule().ID.Name(),
+ nil,
+ )
+ serverOpts.ListenerWrappersRaw = append(serverOpts.ListenerWrappersRaw, jsonListenerWrapper)
+ }
- case "listener_wrappers":
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- modID := "caddy.listeners." + d.Val()
- unm, err := caddyfile.UnmarshalModule(d, modID)
+ case "timeouts":
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
+ switch d.Val() {
+ case "read_body":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
if err != nil {
- return nil, err
+ return nil, d.Errf("parsing read_body timeout duration: %v", err)
}
- listenerWrapper, ok := unm.(caddy.ListenerWrapper)
- if !ok {
- return nil, fmt.Errorf("module %s (%T) is not a listener wrapper", modID, unm)
+ serverOpts.ReadTimeout = caddy.Duration(dur)
+
+ case "read_header":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
}
- jsonListenerWrapper := caddyconfig.JSONModuleObject(
- listenerWrapper,
- "wrapper",
- listenerWrapper.(caddy.Module).CaddyModule().ID.Name(),
- nil,
- )
- serverOpts.ListenerWrappersRaw = append(serverOpts.ListenerWrappersRaw, jsonListenerWrapper)
- }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return nil, d.Errf("parsing read_header timeout duration: %v", err)
+ }
+ serverOpts.ReadHeaderTimeout = caddy.Duration(dur)
- case "timeouts":
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "read_body":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return nil, d.Errf("parsing read_body timeout duration: %v", err)
- }
- serverOpts.ReadTimeout = caddy.Duration(dur)
-
- case "read_header":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return nil, d.Errf("parsing read_header timeout duration: %v", err)
- }
- serverOpts.ReadHeaderTimeout = caddy.Duration(dur)
-
- case "write":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return nil, d.Errf("parsing write timeout duration: %v", err)
- }
- serverOpts.WriteTimeout = caddy.Duration(dur)
-
- case "idle":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return nil, d.Errf("parsing idle timeout duration: %v", err)
- }
- serverOpts.IdleTimeout = caddy.Duration(dur)
-
- default:
- return nil, d.Errf("unrecognized timeouts option '%s'", d.Val())
+ case "write":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
}
- }
- case "keepalive_interval":
- if !d.NextArg() {
- return nil, d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return nil, d.Errf("parsing keepalive interval duration: %v", err)
- }
- serverOpts.KeepAliveInterval = caddy.Duration(dur)
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return nil, d.Errf("parsing write timeout duration: %v", err)
+ }
+ serverOpts.WriteTimeout = caddy.Duration(dur)
- case "max_header_size":
- var sizeStr string
- if !d.AllArgs(&sizeStr) {
- return nil, d.ArgErr()
- }
- size, err := humanize.ParseBytes(sizeStr)
- if err != nil {
- return nil, d.Errf("parsing max_header_size: %v", err)
- }
- serverOpts.MaxHeaderBytes = int(size)
+ case "idle":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return nil, d.Errf("parsing idle timeout duration: %v", err)
+ }
+ serverOpts.IdleTimeout = caddy.Duration(dur)
- case "enable_full_duplex":
- if d.NextArg() {
- return nil, d.ArgErr()
+ default:
+ return nil, d.Errf("unrecognized timeouts option '%s'", d.Val())
}
- serverOpts.EnableFullDuplex = true
+ }
+ case "keepalive_interval":
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return nil, d.Errf("parsing keepalive interval duration: %v", err)
+ }
+ serverOpts.KeepAliveInterval = caddy.Duration(dur)
- case "log_credentials":
- if d.NextArg() {
- return nil, d.ArgErr()
- }
- serverOpts.ShouldLogCredentials = true
+ case "max_header_size":
+ var sizeStr string
+ if !d.AllArgs(&sizeStr) {
+ return nil, d.ArgErr()
+ }
+ size, err := humanize.ParseBytes(sizeStr)
+ if err != nil {
+ return nil, d.Errf("parsing max_header_size: %v", err)
+ }
+ serverOpts.MaxHeaderBytes = int(size)
- case "protocols":
- protos := d.RemainingArgs()
- for _, proto := range protos {
- if proto != "h1" && proto != "h2" && proto != "h2c" && proto != "h3" {
- return nil, d.Errf("unknown protocol '%s': expected h1, h2, h2c, or h3", proto)
- }
- if sliceContains(serverOpts.Protocols, proto) {
- return nil, d.Errf("protocol %s specified more than once", proto)
- }
- serverOpts.Protocols = append(serverOpts.Protocols, proto)
- }
- if nesting := d.Nesting(); d.NextBlock(nesting) {
- return nil, d.ArgErr()
- }
+ case "enable_full_duplex":
+ if d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ serverOpts.EnableFullDuplex = true
- case "strict_sni_host":
- if d.NextArg() && d.Val() != "insecure_off" && d.Val() != "on" {
- return nil, d.Errf("strict_sni_host only supports 'on' or 'insecure_off', got '%s'", d.Val())
- }
- boolVal := true
- if d.Val() == "insecure_off" {
- boolVal = false
- }
- serverOpts.StrictSNIHost = &boolVal
+ case "log_credentials":
+ if d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ serverOpts.ShouldLogCredentials = true
- case "trusted_proxies":
- if !d.NextArg() {
- return nil, d.Err("trusted_proxies expects an IP range source module name as its first argument")
- }
- modID := "http.ip_sources." + d.Val()
- unm, err := caddyfile.UnmarshalModule(d, modID)
- if err != nil {
- return nil, err
+ case "protocols":
+ protos := d.RemainingArgs()
+ for _, proto := range protos {
+ if proto != "h1" && proto != "h2" && proto != "h2c" && proto != "h3" {
+ return nil, d.Errf("unknown protocol '%s': expected h1, h2, h2c, or h3", proto)
}
- source, ok := unm.(caddyhttp.IPRangeSource)
- if !ok {
- return nil, fmt.Errorf("module %s (%T) is not an IP range source", modID, unm)
+ if sliceContains(serverOpts.Protocols, proto) {
+ return nil, d.Errf("protocol %s specified more than once", proto)
}
- jsonSource := caddyconfig.JSONModuleObject(
- source,
- "source",
- source.(caddy.Module).CaddyModule().ID.Name(),
- nil,
- )
- serverOpts.TrustedProxiesRaw = jsonSource
+ serverOpts.Protocols = append(serverOpts.Protocols, proto)
+ }
+ if nesting := d.Nesting(); d.NextBlock(nesting) {
+ return nil, d.ArgErr()
+ }
+
+ case "strict_sni_host":
+ if d.NextArg() && d.Val() != "insecure_off" && d.Val() != "on" {
+ return nil, d.Errf("strict_sni_host only supports 'on' or 'insecure_off', got '%s'", d.Val())
+ }
+ boolVal := true
+ if d.Val() == "insecure_off" {
+ boolVal = false
+ }
+ serverOpts.StrictSNIHost = &boolVal
+
+ case "trusted_proxies":
+ if !d.NextArg() {
+ return nil, d.Err("trusted_proxies expects an IP range source module name as its first argument")
+ }
+ modID := "http.ip_sources." + d.Val()
+ unm, err := caddyfile.UnmarshalModule(d, modID)
+ if err != nil {
+ return nil, err
+ }
+ source, ok := unm.(caddyhttp.IPRangeSource)
+ if !ok {
+ return nil, fmt.Errorf("module %s (%T) is not an IP range source", modID, unm)
+ }
+ jsonSource := caddyconfig.JSONModuleObject(
+ source,
+ "source",
+ source.(caddy.Module).CaddyModule().ID.Name(),
+ nil,
+ )
+ serverOpts.TrustedProxiesRaw = jsonSource
+
+ case "trusted_proxies_strict":
+ if d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ serverOpts.TrustedProxiesStrict = 1
- case "trusted_proxies_strict":
- if d.NextArg() {
- return nil, d.ArgErr()
+ case "client_ip_headers":
+ headers := d.RemainingArgs()
+ for _, header := range headers {
+ if sliceContains(serverOpts.ClientIPHeaders, header) {
+ return nil, d.Errf("client IP header %s specified more than once", header)
}
- serverOpts.TrustedProxiesStrict = 1
+ serverOpts.ClientIPHeaders = append(serverOpts.ClientIPHeaders, header)
+ }
+ if nesting := d.Nesting(); d.NextBlock(nesting) {
+ return nil, d.ArgErr()
+ }
+
+ case "metrics":
+ if d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ if nesting := d.Nesting(); d.NextBlock(nesting) {
+ return nil, d.ArgErr()
+ }
+ serverOpts.Metrics = new(caddyhttp.Metrics)
+
+ // TODO: DEPRECATED. (August 2022)
+ case "protocol":
+ caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol sub-option will be removed soon")
- case "client_ip_headers":
- headers := d.RemainingArgs()
- for _, header := range headers {
- if sliceContains(serverOpts.ClientIPHeaders, header) {
- return nil, d.Errf("client IP header %s specified more than once", header)
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
+ switch d.Val() {
+ case "allow_h2c":
+ caddy.Log().Named("caddyfile").Warn("DEPRECATED: allow_h2c will be removed soon; use protocols option instead")
+
+ if d.NextArg() {
+ return nil, d.ArgErr()
}
- serverOpts.ClientIPHeaders = append(serverOpts.ClientIPHeaders, header)
- }
- if nesting := d.Nesting(); d.NextBlock(nesting) {
- return nil, d.ArgErr()
- }
+ if sliceContains(serverOpts.Protocols, "h2c") {
+ return nil, d.Errf("protocol h2c already specified")
+ }
+ serverOpts.Protocols = append(serverOpts.Protocols, "h2c")
- case "metrics":
- if d.NextArg() {
- return nil, d.ArgErr()
- }
- if nesting := d.Nesting(); d.NextBlock(nesting) {
- return nil, d.ArgErr()
- }
- serverOpts.Metrics = new(caddyhttp.Metrics)
-
- // TODO: DEPRECATED. (August 2022)
- case "protocol":
- caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol sub-option will be removed soon")
-
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "allow_h2c":
- caddy.Log().Named("caddyfile").Warn("DEPRECATED: allow_h2c will be removed soon; use protocols option instead")
-
- if d.NextArg() {
- return nil, d.ArgErr()
- }
- if sliceContains(serverOpts.Protocols, "h2c") {
- return nil, d.Errf("protocol h2c already specified")
- }
- serverOpts.Protocols = append(serverOpts.Protocols, "h2c")
-
- case "strict_sni_host":
- caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol > strict_sni_host in this position will be removed soon; move up to the servers block instead")
-
- if d.NextArg() && d.Val() != "insecure_off" && d.Val() != "on" {
- return nil, d.Errf("strict_sni_host only supports 'on' or 'insecure_off', got '%s'", d.Val())
- }
- boolVal := true
- if d.Val() == "insecure_off" {
- boolVal = false
- }
- serverOpts.StrictSNIHost = &boolVal
-
- default:
- return nil, d.Errf("unrecognized protocol option '%s'", d.Val())
+ case "strict_sni_host":
+ caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol > strict_sni_host in this position will be removed soon; move up to the servers block instead")
+
+ if d.NextArg() && d.Val() != "insecure_off" && d.Val() != "on" {
+ return nil, d.Errf("strict_sni_host only supports 'on' or 'insecure_off', got '%s'", d.Val())
}
- }
+ boolVal := true
+ if d.Val() == "insecure_off" {
+ boolVal = false
+ }
+ serverOpts.StrictSNIHost = &boolVal
- default:
- return nil, d.Errf("unrecognized servers option '%s'", d.Val())
+ default:
+ return nil, d.Errf("unrecognized protocol option '%s'", d.Val())
+ }
}
+
+ default:
+ return nil, d.Errf("unrecognized servers option '%s'", d.Val())
}
}
return serverOpts, nil
diff --git a/caddytest/integration/caddyfile_adapt/push.txt b/caddytest/integration/caddyfile_adapt/push.txt
new file mode 100644
index 000000000..1fe344e09
--- /dev/null
+++ b/caddytest/integration/caddyfile_adapt/push.txt
@@ -0,0 +1,78 @@
+:80
+
+push * /foo.txt
+
+push {
+ GET /foo.txt
+}
+
+push {
+ GET /foo.txt
+ HEAD /foo.txt
+}
+
+push {
+ headers {
+ Foo bar
+ }
+}
+----------
+{
+ "apps": {
+ "http": {
+ "servers": {
+ "srv0": {
+ "listen": [
+ ":80"
+ ],
+ "routes": [
+ {
+ "handle": [
+ {
+ "handler": "push",
+ "resources": [
+ {
+ "target": "/foo.txt"
+ }
+ ]
+ },
+ {
+ "handler": "push",
+ "resources": [
+ {
+ "method": "GET",
+ "target": "/foo.txt"
+ }
+ ]
+ },
+ {
+ "handler": "push",
+ "resources": [
+ {
+ "method": "GET",
+ "target": "/foo.txt"
+ },
+ {
+ "method": "HEAD",
+ "target": "/foo.txt"
+ }
+ ]
+ },
+ {
+ "handler": "push",
+ "headers": {
+ "set": {
+ "Foo": [
+ "bar"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/modules/caddyevents/eventsconfig/caddyfile.go b/modules/caddyevents/eventsconfig/caddyfile.go
index 9c3fae78c..93a4c3d38 100644
--- a/modules/caddyevents/eventsconfig/caddyfile.go
+++ b/modules/caddyevents/eventsconfig/caddyfile.go
@@ -40,14 +40,8 @@ func init() {
//
// If <event> is *, then it will bind to all events.
func parseApp(d *caddyfile.Dispenser, _ any) (any, error) {
+ d.Next() // consume option name
app := new(caddyevents.App)
-
- // consume the option name
- if !d.Next() {
- return nil, d.ArgErr()
- }
-
- // handle the block
for d.NextBlock(0) {
switch d.Val() {
case "on":
diff --git a/modules/caddyhttp/caddyauth/caddyfile.go b/modules/caddyhttp/caddyauth/caddyfile.go
index 05c023209..66201dd94 100644
--- a/modules/caddyhttp/caddyauth/caddyfile.go
+++ b/modules/caddyhttp/caddyauth/caddyfile.go
@@ -34,56 +34,56 @@ func init() {
//
// If no hash algorithm is supplied, bcrypt will be assumed.
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
+ h.Next() // consume directive name
+
var ba HTTPBasicAuth
ba.HashCache = new(Cache)
- for h.Next() {
- var cmp Comparer
- args := h.RemainingArgs()
+ var cmp Comparer
+ args := h.RemainingArgs()
- var hashName string
- switch len(args) {
- case 0:
- hashName = "bcrypt"
- case 1:
- hashName = args[0]
- case 2:
- hashName = args[0]
- ba.Realm = args[1]
- default:
- return nil, h.ArgErr()
- }
-
- switch hashName {
- case "bcrypt":
- cmp = BcryptHash{}
- case "scrypt":
- cmp = ScryptHash{}
- default:
- return nil, h.Errf("unrecognized hash algorithm: %s", hashName)
- }
+ var hashName string
+ switch len(args) {
+ case 0:
+ hashName = "bcrypt"
+ case 1:
+ hashName = args[0]
+ case 2:
+ hashName = args[0]
+ ba.Realm = args[1]
+ default:
+ return nil, h.ArgErr()
+ }
- ba.HashRaw = caddyconfig.JSONModuleObject(cmp, "algorithm", hashName, nil)
+ switch hashName {
+ case "bcrypt":
+ cmp = BcryptHash{}
+ case "scrypt":
+ cmp = ScryptHash{}
+ default:
+ return nil, h.Errf("unrecognized hash algorithm: %s", hashName)
+ }
- for h.NextBlock(0) {
- username := h.Val()
+ ba.HashRaw = caddyconfig.JSONModuleObject(cmp, "algorithm", hashName, nil)
- var b64Pwd, b64Salt string
- h.Args(&b64Pwd, &b64Salt)
- if h.NextArg() {
- return nil, h.ArgErr()
- }
+ for h.NextBlock(0) {
+ username := h.Val()
- if username == "" || b64Pwd == "" {
- return nil, h.Err("username and password cannot be empty or missing")
- }
+ var b64Pwd, b64Salt string
+ h.Args(&b64Pwd, &b64Salt)
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
- ba.AccountList = append(ba.AccountList, Account{
- Username: username,
- Password: b64Pwd,
- Salt: b64Salt,
- })
+ if username == "" || b64Pwd == "" {
+ return nil, h.Err("username and password cannot be empty or missing")
}
+
+ ba.AccountList = append(ba.AccountList, Account{
+ Username: username,
+ Password: b64Pwd,
+ Salt: b64Salt,
+ })
}
return Authentication{
diff --git a/modules/caddyhttp/celmatcher.go b/modules/caddyhttp/celmatcher.go
index e997336ff..65a0e7afa 100644
--- a/modules/caddyhttp/celmatcher.go
+++ b/modules/caddyhttp/celmatcher.go
@@ -176,13 +176,27 @@ func (m MatchExpression) Match(r *http.Request) bool {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (m *MatchExpression) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.CountRemainingArgs() > 1 {
- m.Expr = strings.Join(d.RemainingArgsRaw(), " ")
- } else {
- m.Expr = d.Val()
- }
+ d.Next() // consume matcher name
+
+ // if there's multiple args, then we need to keep the raw
+ // tokens because the user may have used quotes within their
+ // CEL expression (e.g. strings) and we should retain that
+ if d.CountRemainingArgs() > 1 {
+ m.Expr = strings.Join(d.RemainingArgsRaw(), " ")
+ return nil
}
+
+ // there should at least be one arg
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+
+ // if there's only one token, then we can safely grab the
+ // cleaned token (no quotes) and use that as the expression
+ // because there's no valid CEL expression that is only a
+ // quoted string; commonly quotes are used in Caddyfile to
+ // define the expression
+ m.Expr = d.Val()
return nil
}
diff --git a/modules/caddyhttp/encode/caddyfile.go b/modules/caddyhttp/encode/caddyfile.go
index 25d13f7c6..e8ea4b807 100644
--- a/modules/caddyhttp/encode/caddyfile.go
+++ b/modules/caddyhttp/encode/caddyfile.go
@@ -54,62 +54,60 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
//
// Specifying the formats on the first line will use those formats' defaults.
func (enc *Encode) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- var prefer []string
+ d.Next() // consume directive name
- responseMatchers := make(map[string]caddyhttp.ResponseMatcher)
+ prefer := []string{}
+ for _, arg := range d.RemainingArgs() {
+ mod, err := caddy.GetModule("http.encoders." + arg)
+ if err != nil {
+ return d.Errf("finding encoder module '%s': %v", mod, err)
+ }
+ encoding, ok := mod.New().(Encoding)
+ if !ok {
+ return d.Errf("module %s is not an HTTP encoding", mod)
+ }
+ if enc.EncodingsRaw == nil {
+ enc.EncodingsRaw = make(caddy.ModuleMap)
+ }
+ enc.EncodingsRaw[arg] = caddyconfig.JSON(encoding, nil)
+ prefer = append(prefer, arg)
+ }
- for d.Next() {
- for _, arg := range d.RemainingArgs() {
- mod, err := caddy.GetModule("http.encoders." + arg)
+ responseMatchers := make(map[string]caddyhttp.ResponseMatcher)
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "minimum_length":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ minLength, err := strconv.Atoi(d.Val())
if err != nil {
- return d.Errf("finding encoder module '%s': %v", mod, err)
+ return err
}
- encoding, ok := mod.New().(Encoding)
+ enc.MinLength = minLength
+ case "match":
+ err := caddyhttp.ParseNamedResponseMatcher(d.NewFromNextSegment(), responseMatchers)
+ if err != nil {
+ return err
+ }
+ matcher := responseMatchers["match"]
+ enc.Matcher = &matcher
+ default:
+ name := d.Val()
+ modID := "http.encoders." + name
+ unm, err := caddyfile.UnmarshalModule(d, modID)
+ if err != nil {
+ return err
+ }
+ encoding, ok := unm.(Encoding)
if !ok {
- return d.Errf("module %s is not an HTTP encoding", mod)
+ return d.Errf("module %s is not an HTTP encoding; is %T", modID, unm)
}
if enc.EncodingsRaw == nil {
enc.EncodingsRaw = make(caddy.ModuleMap)
}
- enc.EncodingsRaw[arg] = caddyconfig.JSON(encoding, nil)
- prefer = append(prefer, arg)
- }
-
- for d.NextBlock(0) {
- switch d.Val() {
- case "minimum_length":
- if !d.NextArg() {
- return d.ArgErr()
- }
- minLength, err := strconv.Atoi(d.Val())
- if err != nil {
- return err
- }
- enc.MinLength = minLength
- case "match":
- err := caddyhttp.ParseNamedResponseMatcher(d.NewFromNextSegment(), responseMatchers)
- if err != nil {
- return err
- }
- matcher := responseMatchers["match"]
- enc.Matcher = &matcher
- default:
- name := d.Val()
- modID := "http.encoders." + name
- unm, err := caddyfile.UnmarshalModule(d, modID)
- if err != nil {
- return err
- }
- encoding, ok := unm.(Encoding)
- if !ok {
- return d.Errf("module %s is not an HTTP encoding; is %T", modID, unm)
- }
- if enc.EncodingsRaw == nil {
- enc.EncodingsRaw = make(caddy.ModuleMap)
- }
- enc.EncodingsRaw[name] = caddyconfig.JSON(encoding, nil)
- prefer = append(prefer, name)
- }
+ enc.EncodingsRaw[name] = caddyconfig.JSON(encoding, nil)
+ prefer = append(prefer, name)
}
}
diff --git a/modules/caddyhttp/encode/gzip/gzip.go b/modules/caddyhttp/encode/gzip/gzip.go
index 0af38b927..40f37ab8e 100644
--- a/modules/caddyhttp/encode/gzip/gzip.go
+++ b/modules/caddyhttp/encode/gzip/gzip.go
@@ -44,17 +44,16 @@ func (Gzip) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the handler from Caddyfile tokens.
func (g *Gzip) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if !d.NextArg() {
- continue
- }
- levelStr := d.Val()
- level, err := strconv.Atoi(levelStr)
- if err != nil {
- return err
- }
- g.Level = level
+ d.Next() // consume option name
+ if !d.NextArg() {
+ return nil
}
+ levelStr := d.Val()
+ level, err := strconv.Atoi(levelStr)
+ if err != nil {
+ return err
+ }
+ g.Level = level
return nil
}
diff --git a/modules/caddyhttp/fileserver/caddyfile.go b/modules/caddyhttp/fileserver/caddyfile.go
index 94e75fdd1..b18bcdcef 100644
--- a/modules/caddyhttp/fileserver/caddyfile.go
+++ b/modules/caddyhttp/fileserver/caddyfile.go
@@ -223,7 +223,7 @@ func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
// parse out the optional try policy
var tryPolicy string
- for nesting := h.Nesting(); h.NextBlock(nesting); {
+ for h.NextBlock(0) {
switch h.Val() {
case "policy":
if tryPolicy != "" {
diff --git a/modules/caddyhttp/fileserver/matcher.go b/modules/caddyhttp/fileserver/matcher.go
index 310591bcf..d4a40b58d 100644
--- a/modules/caddyhttp/fileserver/matcher.go
+++ b/modules/caddyhttp/fileserver/matcher.go
@@ -127,6 +127,7 @@ func (MatchFile) CaddyModule() caddy.ModuleInfo {
// try_policy first_exist|smallest_size|largest_size|most_recently_modified
// }
func (m *MatchFile) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
+ // iterate to merge multiple matchers into one
for d.Next() {
m.TryFiles = append(m.TryFiles, d.RemainingArgs()...)
for d.NextBlock(0) {
diff --git a/modules/caddyhttp/headers/caddyfile.go b/modules/caddyhttp/headers/caddyfile.go
index 2b069100b..821c0d830 100644
--- a/modules/caddyhttp/headers/caddyfile.go
+++ b/modules/caddyhttp/headers/caddyfile.go
@@ -47,14 +47,12 @@ func init() {
// ? conditionally sets a value only if the header field is not already set,
// and > sets a field with defer enabled.
func parseCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
- if !h.Next() {
- return nil, h.ArgErr()
- }
-
+ h.Next() // consume directive name
matcherSet, err := h.ExtractMatcherSet()
if err != nil {
return nil, err
}
+ h.Next() // consume the directive name again (matcher parsing resets)
makeHandler := func() Handler {
return Handler{
@@ -65,73 +63,71 @@ func parseCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
}
handler, handlerWithRequire := makeHandler(), makeHandler()
- for h.Next() {
- // first see if headers are in the initial line
- var hasArgs bool
+ // first see if headers are in the initial line
+ var hasArgs bool
+ if h.NextArg() {
+ hasArgs = true
+ field := h.Val()
+ var value, replacement string
if h.NextArg() {
- hasArgs = true
- field := h.Val()
- var value, replacement string
- if h.NextArg() {
- value = h.Val()
- }
- if h.NextArg() {
- replacement = h.Val()
- }
- err := applyHeaderOp(
- handler.Response.HeaderOps,
- handler.Response,
- field,
- value,
- replacement,
- )
- if err != nil {
- return nil, h.Err(err.Error())
- }
- if len(handler.Response.HeaderOps.Delete) > 0 {
- handler.Response.Deferred = true
- }
+ value = h.Val()
}
+ if h.NextArg() {
+ replacement = h.Val()
+ }
+ err := applyHeaderOp(
+ handler.Response.HeaderOps,
+ handler.Response,
+ field,
+ value,
+ replacement,
+ )
+ if err != nil {
+ return nil, h.Err(err.Error())
+ }
+ if len(handler.Response.HeaderOps.Delete) > 0 {
+ handler.Response.Deferred = true
+ }
+ }
- // if not, they should be in a block
- for h.NextBlock(0) {
- field := h.Val()
- if field == "defer" {
- handler.Response.Deferred = true
- continue
- }
- if hasArgs {
- return nil, h.Err("cannot specify headers in both arguments and block") // because it would be weird
- }
+ // if not, they should be in a block
+ for h.NextBlock(0) {
+ field := h.Val()
+ if field == "defer" {
+ handler.Response.Deferred = true
+ continue
+ }
+ if hasArgs {
+ return nil, h.Err("cannot specify headers in both arguments and block") // because it would be weird
+ }
- // sometimes it is habitual for users to suffix a field name with a colon,
- // as if they were writing a curl command or something; see
- // https://caddy.community/t/v2-reverse-proxy-please-add-cors-example-to-the-docs/7349/19
- field = strings.TrimSuffix(field, ":")
+ // sometimes it is habitual for users to suffix a field name with a colon,
+ // as if they were writing a curl command or something; see
+ // https://caddy.community/t/v2-reverse-proxy-please-add-cors-example-to-the-docs/7349/19
+ field = strings.TrimSuffix(field, ":")
- var value, replacement string
- if h.NextArg() {
- value = h.Val()
- }
- if h.NextArg() {
- replacement = h.Val()
- }
+ var value, replacement string
+ if h.NextArg() {
+ value = h.Val()
+ }
+ if h.NextArg() {
+ replacement = h.Val()
+ }
- handlerToUse := handler
- if strings.HasPrefix(field, "?") {
- handlerToUse = handlerWithRequire
- }
+ handlerToUse := handler
+ if strings.HasPrefix(field, "?") {
+ handlerToUse = handlerWithRequire
+ }
- err := applyHeaderOp(
- handlerToUse.Response.HeaderOps,
- handlerToUse.Response,
- field,
- value,
- replacement,
- )
- if err != nil {
- return nil, h.Err(err.Error())
- }
+ err := applyHeaderOp(
+ handlerToUse.Response.HeaderOps,
+ handlerToUse.Response,
+ field,
+ value,
+ replacement,
+ )
+ if err != nil {
+ return nil, h.Err(err.Error())
}
}
@@ -151,55 +147,51 @@ func parseCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
//
// request_header [<matcher>] [[+|-]<field> [<value|regexp>] [<replacement>]]
func parseReqHdrCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
- if !h.Next() {
- return nil, h.ArgErr()
- }
-
+ h.Next() // consume directive name
matcherSet, err := h.ExtractMatcherSet()
if err != nil {
return nil, err
}
+ h.Next() // consume the directive name again (matcher parsing resets)
configValues := []httpcaddyfile.ConfigValue{}
- for h.Next() {
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- field := h.Val()
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ field := h.Val()
- hdr := Handler{
- Request: &HeaderOps{},
- }
+ hdr := Handler{
+ Request: &HeaderOps{},
+ }
- // sometimes it is habitual for users to suffix a field name with a colon,
- // as if they were writing a curl command or something; see
- // https://caddy.community/t/v2-reverse-proxy-please-add-cors-example-to-the-docs/7349/19
- field = strings.TrimSuffix(field, ":")
+ // sometimes it is habitual for users to suffix a field name with a colon,
+ // as if they were writing a curl command or something; see
+ // https://caddy.community/t/v2-reverse-proxy-please-add-cors-example-to-the-docs/7349/19
+ field = strings.TrimSuffix(field, ":")
- var value, replacement string
- if h.NextArg() {
- value = h.Val()
- }
+ var value, replacement string
+ if h.NextArg() {
+ value = h.Val()
+ }
+ if h.NextArg() {
+ replacement = h.Val()
if h.NextArg() {
- replacement = h.Val()
- if h.NextArg() {
- return nil, h.ArgErr()
- }
+ return nil, h.ArgErr()
}
+ }
- if hdr.Request == nil {
- hdr.Request = new(HeaderOps)
- }
- if err := CaddyfileHeaderOp(hdr.Request, field, value, replacement); err != nil {
- return nil, h.Err(err.Error())
- }
+ if hdr.Request == nil {
+ hdr.Request = new(HeaderOps)
+ }
+ if err := CaddyfileHeaderOp(hdr.Request, field, value, replacement); err != nil {
+ return nil, h.Err(err.Error())
+ }
- configValues = append(configValues, h.NewRoute(matcherSet, hdr)...)
+ configValues = append(configValues, h.NewRoute(matcherSet, hdr)...)
- if h.NextArg() {
- return nil, h.ArgErr()
- }
+ if h.NextArg() {
+ return nil, h.ArgErr()
}
return configValues, nil
}
diff --git a/modules/caddyhttp/ip_matchers.go b/modules/caddyhttp/ip_matchers.go
index 57a229578..30be6120c 100644
--- a/modules/caddyhttp/ip_matchers.go
+++ b/modules/caddyhttp/ip_matchers.go
@@ -79,24 +79,23 @@ func (MatchRemoteIP) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- for d.NextArg() {
- if d.Val() == "forwarded" {
- if len(m.Ranges) > 0 {
- return d.Err("if used, 'forwarded' must be first argument")
- }
- m.Forwarded = true
- continue
- }
- if d.Val() == "private_ranges" {
- m.Ranges = append(m.Ranges, PrivateRangesCIDR()...)
- continue
+ d.Next() // consume matcher name
+ for d.NextArg() {
+ if d.Val() == "forwarded" {
+ if len(m.Ranges) > 0 {
+ return d.Err("if used, 'forwarded' must be first argument")
}
- m.Ranges = append(m.Ranges, d.Val())
+ m.Forwarded = true
+ continue
}
- if d.NextBlock(0) {
- return d.Err("malformed remote_ip matcher: blocks are not supported")
+ if d.Val() == "private_ranges" {
+ m.Ranges = append(m.Ranges, PrivateRangesCIDR()...)
+ continue
}
+ m.Ranges = append(m.Ranges, d.Val())
+ }
+ if d.NextBlock(0) {
+ return d.Err("malformed remote_ip matcher: blocks are not supported")
}
return nil
}
@@ -189,17 +188,16 @@ func (MatchClientIP) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (m *MatchClientIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- for d.NextArg() {
- if d.Val() == "private_ranges" {
- m.Ranges = append(m.Ranges, PrivateRangesCIDR()...)
- continue
- }
- m.Ranges = append(m.Ranges, d.Val())
- }
- if d.NextBlock(0) {
- return d.Err("malformed client_ip matcher: blocks are not supported")
+ d.Next() // consume matcher name
+ for d.NextArg() {
+ if d.Val() == "private_ranges" {
+ m.Ranges = append(m.Ranges, PrivateRangesCIDR()...)
+ continue
}
+ m.Ranges = append(m.Ranges, d.Val())
+ }
+ if d.NextBlock(0) {
+ return d.Err("malformed client_ip matcher: blocks are not supported")
}
return nil
}
diff --git a/modules/caddyhttp/map/caddyfile.go b/modules/caddyhttp/map/caddyfile.go
index 9cc7d8c6d..8f7b5d34e 100644
--- a/modules/caddyhttp/map/caddyfile.go
+++ b/modules/caddyhttp/map/caddyfile.go
@@ -42,74 +42,73 @@ func init() {
// However, for convenience, there may be fewer outputs than destinations and any missing
// outputs will be filled in implicitly.
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
+ h.Next() // consume directive name
+
var handler Handler
- for h.Next() {
- // source
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- handler.Source = h.Val()
+ // source
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ handler.Source = h.Val()
- // destinations
- handler.Destinations = h.RemainingArgs()
- if len(handler.Destinations) == 0 {
- return nil, h.Err("missing destination argument(s)")
- }
- for _, dest := range handler.Destinations {
- if shorthand := httpcaddyfile.WasReplacedPlaceholderShorthand(dest); shorthand != "" {
- return nil, h.Errf("destination %s conflicts with a Caddyfile placeholder shorthand", shorthand)
- }
+ // destinations
+ handler.Destinations = h.RemainingArgs()
+ if len(handler.Destinations) == 0 {
+ return nil, h.Err("missing destination argument(s)")
+ }
+ for _, dest := range handler.Destinations {
+ if shorthand := httpcaddyfile.WasReplacedPlaceholderShorthand(dest); shorthand != "" {
+ return nil, h.Errf("destination %s conflicts with a Caddyfile placeholder shorthand", shorthand)
}
+ }
- // mappings
- for h.NextBlock(0) {
- // defaults are a special case
- if h.Val() == "default" {
- if len(handler.Defaults) > 0 {
- return nil, h.Err("defaults already defined")
- }
- handler.Defaults = h.RemainingArgs()
- for len(handler.Defaults) < len(handler.Destinations) {
- handler.Defaults = append(handler.Defaults, "")
- }
- continue
- }
-
- // every line maps an input value to one or more outputs
- in := h.Val()
- var outs []any
- for h.NextArg() {
- val := h.ScalarVal()
- if val == "-" {
- outs = append(outs, nil)
- } else {
- outs = append(outs, val)
- }
+ // mappings
+ for h.NextBlock(0) {
+ // defaults are a special case
+ if h.Val() == "default" {
+ if len(handler.Defaults) > 0 {
+ return nil, h.Err("defaults already defined")
}
-
- // cannot have more outputs than destinations
- if len(outs) > len(handler.Destinations) {
- return nil, h.Err("too many outputs")
+ handler.Defaults = h.RemainingArgs()
+ for len(handler.Defaults) < len(handler.Destinations) {
+ handler.Defaults = append(handler.Defaults, "")
}
+ continue
+ }
- // for convenience, can have fewer outputs than destinations, but the
- // underlying handler won't accept that, so we fill in nil values
- for len(outs) < len(handler.Destinations) {
+ // every line maps an input value to one or more outputs
+ in := h.Val()
+ var outs []any
+ for h.NextArg() {
+ val := h.ScalarVal()
+ if val == "-" {
outs = append(outs, nil)
- }
-
- // create the mapping
- mapping := Mapping{Outputs: outs}
- if strings.HasPrefix(in, "~") {
- mapping.InputRegexp = in[1:]
} else {
- mapping.Input = in
+ outs = append(outs, val)
}
+ }
- handler.Mappings = append(handler.Mappings, mapping)
+ // cannot have more outputs than destinations
+ if len(outs) > len(handler.Destinations) {
+ return nil, h.Err("too many outputs")
}
- }
+ // for convenience, can have fewer outputs than destinations, but the
+ // underlying handler won't accept that, so we fill in nil values
+ for len(outs) < len(handler.Destinations) {
+ outs = append(outs, nil)
+ }
+
+ // create the mapping
+ mapping := Mapping{Outputs: outs}
+ if strings.HasPrefix(in, "~") {
+ mapping.InputRegexp = in[1:]
+ } else {
+ mapping.Input = in
+ }
+
+ handler.Mappings = append(handler.Mappings, mapping)
+ }
return handler, nil
}
diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go
index 93211b220..f01f187fa 100644
--- a/modules/caddyhttp/matchers.go
+++ b/modules/caddyhttp/matchers.go
@@ -225,6 +225,7 @@ func (MatchHost) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (m *MatchHost) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
+ // iterate to merge multiple matchers into one
for d.Next() {
*m = append(*m, d.RemainingArgs()...)
if d.NextBlock(0) {
@@ -632,6 +633,7 @@ func (MatchPath) CELLibrary(ctx caddy.Context) (cel.Library, error) {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (m *MatchPath) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
+ // iterate to merge multiple matchers into one
for d.Next() {
*m = append(*m, d.RemainingArgs()...)
if d.NextBlock(0) {
@@ -716,6 +718,7 @@ func (MatchMethod) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (m *MatchMethod) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
+ // iterate to merge multiple matchers into one
for d.Next() {
*m = append(*m, d.RemainingArgs()...)
if d.NextBlock(0) {
@@ -770,6 +773,7 @@ func (m *MatchQuery) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if *m == nil {
*m = make(map[string][]string)
}
+ // iterate to merge multiple matchers into one
for d.Next() {
for _, query := range d.RemainingArgs() {
if query == "" {
@@ -868,6 +872,7 @@ func (m *MatchHeader) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if *m == nil {
*m = make(map[string][]string)
}
+ // iterate to merge multiple matchers into one
for d.Next() {
var field, val string
if !d.Args(&field) {
@@ -1002,6 +1007,7 @@ func (m *MatchHeaderRE) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if *m == nil {
*m = make(map[string]*MatchRegexp)
}
+ // iterate to merge multiple matchers into one
for d.Next() {
var first, second, third string
if !d.Args(&first, &second) {
@@ -1166,6 +1172,7 @@ func (m MatchProtocol) Match(r *http.Request) bool {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (m *MatchProtocol) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
+ // iterate to merge multiple matchers into one
for d.Next() {
var proto string
if !d.Args(&proto) {
@@ -1207,6 +1214,7 @@ func (MatchNot) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (m *MatchNot) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
+ // iterate to merge multiple matchers into one
for d.Next() {
matcherSet, err := ParseCaddyfileNestedMatcherSet(d)
if err != nil {
@@ -1331,6 +1339,7 @@ func (mre *MatchRegexp) Match(input string, repl *caddy.Replacer) bool {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (mre *MatchRegexp) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
+ // iterate to merge multiple matchers into one
for d.Next() {
// If this is the second iteration of the loop
// then there's more than one path_regexp matcher
diff --git a/modules/caddyhttp/proxyprotocol/module.go b/modules/caddyhttp/proxyprotocol/module.go
index c6dc283ea..75a156a20 100644
--- a/modules/caddyhttp/proxyprotocol/module.go
+++ b/modules/caddyhttp/proxyprotocol/module.go
@@ -39,40 +39,40 @@ func (ListenerWrapper) CaddyModule() caddy.ModuleInfo {
// fallback_policy <policy>
// }
func (w *ListenerWrapper) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- // No same-line options are supported
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume wrapper name
- for d.NextBlock(0) {
- switch d.Val() {
- case "timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("parsing proxy_protocol timeout duration: %v", err)
- }
- w.Timeout = caddy.Duration(dur)
+ // No same-line options are supported
+ if d.NextArg() {
+ return d.ArgErr()
+ }
- case "allow":
- w.Allow = append(w.Allow, d.RemainingArgs()...)
- case "deny":
- w.Deny = append(w.Deny, d.RemainingArgs()...)
- case "fallback_policy":
- if !d.NextArg() {
- return d.ArgErr()
- }
- p, err := parsePolicy(d.Val())
- if err != nil {
- return d.WrapErr(err)
- }
- w.FallbackPolicy = p
- default:
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "timeout":
+ if !d.NextArg() {
return d.ArgErr()
}
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("parsing proxy_protocol timeout duration: %v", err)
+ }
+ w.Timeout = caddy.Duration(dur)
+
+ case "allow":
+ w.Allow = append(w.Allow, d.RemainingArgs()...)
+ case "deny":
+ w.Deny = append(w.Deny, d.RemainingArgs()...)
+ case "fallback_policy":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ p, err := parsePolicy(d.Val())
+ if err != nil {
+ return d.WrapErr(err)
+ }
+ w.FallbackPolicy = p
+ default:
+ return d.ArgErr()
}
}
return nil
diff --git a/modules/caddyhttp/push/caddyfile.go b/modules/caddyhttp/push/caddyfile.go
index 963117c1c..07f6ccea7 100644
--- a/modules/caddyhttp/push/caddyfile.go
+++ b/modules/caddyhttp/push/caddyfile.go
@@ -44,63 +44,63 @@ func init() {
// Placeholders are accepted in resource and header field
// name and value and replacement tokens.
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
- handler := new(Handler)
-
- for h.Next() {
- if h.NextArg() {
- handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
- }
+ h.Next() // consume directive name
- // optional block
- for outerNesting := h.Nesting(); h.NextBlock(outerNesting); {
- switch h.Val() {
- case "headers":
- if h.NextArg() {
- return nil, h.ArgErr()
- }
- for innerNesting := h.Nesting(); h.NextBlock(innerNesting); {
- var err error
+ handler := new(Handler)
- // include current token, which we treat as an argument here
- args := []string{h.Val()}
- args = append(args, h.RemainingArgs()...)
+ // inline resources
+ if h.NextArg() {
+ handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
+ }
- if handler.Headers == nil {
- handler.Headers = new(HeaderConfig)
- }
+ // optional block
+ for h.NextBlock(0) {
+ switch h.Val() {
+ case "headers":
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ for nesting := h.Nesting(); h.NextBlock(nesting); {
+ var err error
- switch len(args) {
- case 1:
- err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], "", "")
- case 2:
- err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], args[1], "")
- case 3:
- err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], args[1], args[2])
- default:
- return nil, h.ArgErr()
- }
+ // include current token, which we treat as an argument here
+ args := []string{h.Val()}
+ args = append(args, h.RemainingArgs()...)
- if err != nil {
- return nil, h.Err(err.Error())
- }
+ if handler.Headers == nil {
+ handler.Headers = new(HeaderConfig)
}
- case "GET", "HEAD":
- method := h.Val()
- if !h.NextArg() {
+ switch len(args) {
+ case 1:
+ err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], "", "")
+ case 2:
+ err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], args[1], "")
+ case 3:
+ err = headers.CaddyfileHeaderOp(&handler.Headers.HeaderOps, args[0], args[1], args[2])
+ default:
return nil, h.ArgErr()
}
- target := h.Val()
- handler.Resources = append(handler.Resources, Resource{
- Method: method,
- Target: target,
- })
- default:
- handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
+ if err != nil {
+ return nil, h.Err(err.Error())
+ }
+ }
+
+ case "GET", "HEAD":
+ method := h.Val()
+ if !h.NextArg() {
+ return nil, h.ArgErr()
}
+ target := h.Val()
+ handler.Resources = append(handler.Resources, Resource{
+ Method: method,
+ Target: target,
+ })
+
+ default:
+ handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
}
}
-
return handler, nil
}
diff --git a/modules/caddyhttp/requestbody/caddyfile.go b/modules/caddyhttp/requestbody/caddyfile.go
index 8a92909fb..d2956cae0 100644
--- a/modules/caddyhttp/requestbody/caddyfile.go
+++ b/modules/caddyhttp/requestbody/caddyfile.go
@@ -26,25 +26,26 @@ func init() {
}
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
+ h.Next() // consume directive name
+
rb := new(RequestBody)
- for h.Next() {
- // configuration should be in a block
- for h.NextBlock(0) {
- switch h.Val() {
- case "max_size":
- var sizeStr string
- if !h.AllArgs(&sizeStr) {
- return nil, h.ArgErr()
- }
- size, err := humanize.ParseBytes(sizeStr)
- if err != nil {
- return nil, h.Errf("parsing max_size: %v", err)
- }
- rb.MaxSize = int64(size)
- default:
- return nil, h.Errf("unrecognized servers option '%s'", h.Val())
+ // configuration should be in a block
+ for h.NextBlock(0) {
+ switch h.Val() {
+ case "max_size":
+ var sizeStr string
+ if !h.AllArgs(&sizeStr) {
+ return nil, h.ArgErr()
+ }
+ size, err := humanize.ParseBytes(sizeStr)
+ if err != nil {
+ return nil, h.Errf("parsing max_size: %v", err)
}
+ rb.MaxSize = int64(size)
+
+ default:
+ return nil, h.Errf("unrecognized servers option '%s'", h.Val())
}
}
diff --git a/modules/caddyhttp/responsematchers.go b/modules/caddyhttp/responsematchers.go
index 6bac7800b..cf96b00cd 100644
--- a/modules/caddyhttp/responsematchers.go
+++ b/modules/caddyhttp/responsematchers.go
@@ -67,55 +67,53 @@ func (rm ResponseMatcher) matchStatusCode(statusCode int) bool {
//
// @name [header <field> [<value>]] | [status <code...>]
func ParseNamedResponseMatcher(d *caddyfile.Dispenser, matchers map[string]ResponseMatcher) error {
- for d.Next() {
- definitionName := d.Val()
+ d.Next() // consume matcher name
+ definitionName := d.Val()
- if _, ok := matchers[definitionName]; ok {
- return d.Errf("matcher is defined more than once: %s", definitionName)
- }
+ if _, ok := matchers[definitionName]; ok {
+ return d.Errf("matcher is defined more than once: %s", definitionName)
+ }
- matcher := ResponseMatcher{}
- for nesting := d.Nesting(); d.NextArg() || d.NextBlock(nesting); {
- switch d.Val() {
- case "header":
- if matcher.Headers == nil {
- matcher.Headers = http.Header{}
- }
+ matcher := ResponseMatcher{}
+ for nesting := d.Nesting(); d.NextArg() || d.NextBlock(nesting); {
+ switch d.Val() {
+ case "header":
+ if matcher.Headers == nil {
+ matcher.Headers = http.Header{}
+ }
- // reuse the header request matcher's unmarshaler
- headerMatcher := MatchHeader(matcher.Headers)
- err := headerMatcher.UnmarshalCaddyfile(d.NewFromNextSegment())
- if err != nil {
- return err
- }
+ // reuse the header request matcher's unmarshaler
+ headerMatcher := MatchHeader(matcher.Headers)
+ err := headerMatcher.UnmarshalCaddyfile(d.NewFromNextSegment())
+ if err != nil {
+ return err
+ }
- matcher.Headers = http.Header(headerMatcher)
- case "status":
- if matcher.StatusCode == nil {
- matcher.StatusCode = []int{}
- }
+ matcher.Headers = http.Header(headerMatcher)
+ case "status":
+ if matcher.StatusCode == nil {
+ matcher.StatusCode = []int{}
+ }
- args := d.RemainingArgs()
- if len(args) == 0 {
- return d.ArgErr()
- }
+ args := d.RemainingArgs()
+ if len(args) == 0 {
+ return d.ArgErr()
+ }
- for _, arg := range args {
- if len(arg) == 3 && strings.HasSuffix(arg, "xx") {
- arg = arg[:1]
- }
- statusNum, err := strconv.Atoi(arg)
- if err != nil {
- return d.Errf("bad status value '%s': %v", arg, err)
- }
- matcher.StatusCode = append(matcher.StatusCode, statusNum)
+ for _, arg := range args {
+ if len(arg) == 3 && strings.HasSuffix(arg, "xx") {
+ arg = arg[:1]
}
- default:
- return d.Errf("unrecognized response matcher %s", d.Val())
+ statusNum, err := strconv.Atoi(arg)
+ if err != nil {
+ return d.Errf("bad status value '%s': %v", arg, err)
+ }
+ matcher.StatusCode = append(matcher.StatusCode, statusNum)
}
+ default:
+ return d.Errf("unrecognized response matcher %s", d.Val())
}
-
- matchers[definitionName] = matcher
}
+ matchers[definitionName] = matcher
return nil
}
diff --git a/modules/caddyhttp/reverseproxy/caddyfile.go b/modules/caddyhttp/reverseproxy/caddyfile.go
index 4e01c7a1b..42fd6f99d 100644
--- a/modules/caddyhttp/reverseproxy/caddyfile.go
+++ b/modules/caddyhttp/reverseproxy/caddyfile.go
@@ -210,7 +210,7 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
}
}
- for nesting := d.Nesting(); d.NextBlock(nesting); {
+ for d.NextBlock(0) {
// if the subdirective has an "@" prefix then we
// parse it as a response matcher for use with "handle_response"
if strings.HasPrefix(d.Val(), matcherPrefix) {
@@ -774,7 +774,7 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
}
// make sure there's no block, cause it doesn't make sense
- if d.NextBlock(1) {
+ if nesting := d.Nesting(); d.NextBlock(nesting) {
return d.Errf("cannot define routes for 'replace_status', use 'handle_response' instead.")
}
@@ -930,297 +930,296 @@ func (h *Handler) FinalizeUnmarshalCaddyfile(helper httpcaddyfile.Helper) error
// max_idle_conns_per_host <count>
// }
func (h *HTTPTransport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- for d.NextBlock(0) {
- switch d.Val() {
- case "read_buffer":
- if !d.NextArg() {
- return d.ArgErr()
- }
- size, err := humanize.ParseBytes(d.Val())
- if err != nil {
- return d.Errf("invalid read buffer size '%s': %v", d.Val(), err)
- }
- h.ReadBufferSize = int(size)
-
- case "write_buffer":
- if !d.NextArg() {
- return d.ArgErr()
- }
- size, err := humanize.ParseBytes(d.Val())
- if err != nil {
- return d.Errf("invalid write buffer size '%s': %v", d.Val(), err)
- }
- h.WriteBufferSize = int(size)
+ d.Next() // consume transport name
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "read_buffer":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ size, err := humanize.ParseBytes(d.Val())
+ if err != nil {
+ return d.Errf("invalid read buffer size '%s': %v", d.Val(), err)
+ }
+ h.ReadBufferSize = int(size)
- case "read_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- timeout, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("invalid read timeout duration '%s': %v", d.Val(), err)
- }
- h.ReadTimeout = caddy.Duration(timeout)
+ case "write_buffer":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ size, err := humanize.ParseBytes(d.Val())
+ if err != nil {
+ return d.Errf("invalid write buffer size '%s': %v", d.Val(), err)
+ }
+ h.WriteBufferSize = int(size)
- case "write_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- timeout, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("invalid write timeout duration '%s': %v", d.Val(), err)
- }
- h.WriteTimeout = caddy.Duration(timeout)
+ case "read_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ timeout, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("invalid read timeout duration '%s': %v", d.Val(), err)
+ }
+ h.ReadTimeout = caddy.Duration(timeout)
- case "max_response_header":
- if !d.NextArg() {
- return d.ArgErr()
- }
- size, err := humanize.ParseBytes(d.Val())
- if err != nil {
- return d.Errf("invalid max response header size '%s': %v", d.Val(), err)
- }
- h.MaxResponseHeaderSize = int64(size)
+ case "write_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ timeout, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("invalid write timeout duration '%s': %v", d.Val(), err)
+ }
+ h.WriteTimeout = caddy.Duration(timeout)
- case "proxy_protocol":
- if !d.NextArg() {
- return d.ArgErr()
- }
- switch proxyProtocol := d.Val(); proxyProtocol {
- case "v1", "v2":
- h.ProxyProtocol = proxyProtocol
- default:
- return d.Errf("invalid proxy protocol version '%s'", proxyProtocol)
- }
+ case "max_response_header":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ size, err := humanize.ParseBytes(d.Val())
+ if err != nil {
+ return d.Errf("invalid max response header size '%s': %v", d.Val(), err)
+ }
+ h.MaxResponseHeaderSize = int64(size)
- case "dial_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
- }
- h.DialTimeout = caddy.Duration(dur)
+ case "proxy_protocol":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ switch proxyProtocol := d.Val(); proxyProtocol {
+ case "v1", "v2":
+ h.ProxyProtocol = proxyProtocol
+ default:
+ return d.Errf("invalid proxy protocol version '%s'", proxyProtocol)
+ }
- case "dial_fallback_delay":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad fallback delay value '%s': %v", d.Val(), err)
- }
- h.FallbackDelay = caddy.Duration(dur)
+ case "dial_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
+ }
+ h.DialTimeout = caddy.Duration(dur)
- case "response_header_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
- }
- h.ResponseHeaderTimeout = caddy.Duration(dur)
+ case "dial_fallback_delay":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad fallback delay value '%s': %v", d.Val(), err)
+ }
+ h.FallbackDelay = caddy.Duration(dur)
- case "expect_continue_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
- }
- h.ExpectContinueTimeout = caddy.Duration(dur)
+ case "response_header_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
+ }
+ h.ResponseHeaderTimeout = caddy.Duration(dur)
- case "resolvers":
- if h.Resolver == nil {
- h.Resolver = new(UpstreamResolver)
- }
- h.Resolver.Addresses = d.RemainingArgs()
- if len(h.Resolver.Addresses) == 0 {
- return d.Errf("must specify at least one resolver address")
- }
+ case "expect_continue_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
+ }
+ h.ExpectContinueTimeout = caddy.Duration(dur)
- case "tls":
- if h.TLS == nil {
- h.TLS = new(TLSConfig)
- }
+ case "resolvers":
+ if h.Resolver == nil {
+ h.Resolver = new(UpstreamResolver)
+ }
+ h.Resolver.Addresses = d.RemainingArgs()
+ if len(h.Resolver.Addresses) == 0 {
+ return d.Errf("must specify at least one resolver address")
+ }
- case "tls_client_auth":
- if h.TLS == nil {
- h.TLS = new(TLSConfig)
- }
- args := d.RemainingArgs()
- switch len(args) {
- case 1:
- h.TLS.ClientCertificateAutomate = args[0]
- case 2:
- h.TLS.ClientCertificateFile = args[0]
- h.TLS.ClientCertificateKeyFile = args[1]
- default:
- return d.ArgErr()
- }
+ case "tls":
+ if h.TLS == nil {
+ h.TLS = new(TLSConfig)
+ }
- case "tls_insecure_skip_verify":
- if d.NextArg() {
- return d.ArgErr()
- }
- if h.TLS == nil {
- h.TLS = new(TLSConfig)
- }
- h.TLS.InsecureSkipVerify = true
+ case "tls_client_auth":
+ if h.TLS == nil {
+ h.TLS = new(TLSConfig)
+ }
+ args := d.RemainingArgs()
+ switch len(args) {
+ case 1:
+ h.TLS.ClientCertificateAutomate = args[0]
+ case 2:
+ h.TLS.ClientCertificateFile = args[0]
+ h.TLS.ClientCertificateKeyFile = args[1]
+ default:
+ return d.ArgErr()
+ }
- case "tls_curves":
- args := d.RemainingArgs()
- if len(args) == 0 {
- return d.ArgErr()
- }
- if h.TLS == nil {
- h.TLS = new(TLSConfig)
- }
- h.TLS.Curves = args
+ case "tls_insecure_skip_verify":
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+ if h.TLS == nil {
+ h.TLS = new(TLSConfig)
+ }
+ h.TLS.InsecureSkipVerify = true
- case "tls_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
- }
- if h.TLS == nil {
- h.TLS = new(TLSConfig)
- }
- h.TLS.HandshakeTimeout = caddy.Duration(dur)
+ case "tls_curves":
+ args := d.RemainingArgs()
+ if len(args) == 0 {
+ return d.ArgErr()
+ }
+ if h.TLS == nil {
+ h.TLS = new(TLSConfig)
+ }
+ h.TLS.Curves = args
- case "tls_trusted_ca_certs":
- args := d.RemainingArgs()
- if len(args) == 0 {
- return d.ArgErr()
- }
- if h.TLS == nil {
- h.TLS = new(TLSConfig)
- }
- h.TLS.RootCAPEMFiles = args
+ case "tls_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
+ }
+ if h.TLS == nil {
+ h.TLS = new(TLSConfig)
+ }
+ h.TLS.HandshakeTimeout = caddy.Duration(dur)
- case "tls_server_name":
- if !d.NextArg() {
- return d.ArgErr()
- }
- if h.TLS == nil {
- h.TLS = new(TLSConfig)
- }
- h.TLS.ServerName = d.Val()
+ case "tls_trusted_ca_certs":
+ args := d.RemainingArgs()
+ if len(args) == 0 {
+ return d.ArgErr()
+ }
+ if h.TLS == nil {
+ h.TLS = new(TLSConfig)
+ }
+ h.TLS.RootCAPEMFiles = args
- case "tls_renegotiation":
- if h.TLS == nil {
- h.TLS = new(TLSConfig)
- }
- if !d.NextArg() {
- return d.ArgErr()
- }
- switch renegotiation := d.Val(); renegotiation {
- case "never", "once", "freely":
- h.TLS.Renegotiation = renegotiation
- default:
- return d.ArgErr()
- }
+ case "tls_server_name":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ if h.TLS == nil {
+ h.TLS = new(TLSConfig)
+ }
+ h.TLS.ServerName = d.Val()
- case "tls_except_ports":
- if h.TLS == nil {
- h.TLS = new(TLSConfig)
- }
- h.TLS.ExceptPorts = d.RemainingArgs()
- if len(h.TLS.ExceptPorts) == 0 {
- return d.ArgErr()
- }
+ case "tls_renegotiation":
+ if h.TLS == nil {
+ h.TLS = new(TLSConfig)
+ }
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ switch renegotiation := d.Val(); renegotiation {
+ case "never", "once", "freely":
+ h.TLS.Renegotiation = renegotiation
+ default:
+ return d.ArgErr()
+ }
- case "keepalive":
- if !d.NextArg() {
- return d.ArgErr()
- }
- if h.KeepAlive == nil {
- h.KeepAlive = new(KeepAlive)
- }
- if d.Val() == "off" {
- var disable bool
- h.KeepAlive.Enabled = &disable
- break
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad duration value '%s': %v", d.Val(), err)
- }
- h.KeepAlive.IdleConnTimeout = caddy.Duration(dur)
+ case "tls_except_ports":
+ if h.TLS == nil {
+ h.TLS = new(TLSConfig)
+ }
+ h.TLS.ExceptPorts = d.RemainingArgs()
+ if len(h.TLS.ExceptPorts) == 0 {
+ return d.ArgErr()
+ }
- case "keepalive_interval":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad interval value '%s': %v", d.Val(), err)
- }
- if h.KeepAlive == nil {
- h.KeepAlive = new(KeepAlive)
- }
- h.KeepAlive.ProbeInterval = caddy.Duration(dur)
+ case "keepalive":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ if h.KeepAlive == nil {
+ h.KeepAlive = new(KeepAlive)
+ }
+ if d.Val() == "off" {
+ var disable bool
+ h.KeepAlive.Enabled = &disable
+ break
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad duration value '%s': %v", d.Val(), err)
+ }
+ h.KeepAlive.IdleConnTimeout = caddy.Duration(dur)
- case "keepalive_idle_conns":
- if !d.NextArg() {
- return d.ArgErr()
- }
- num, err := strconv.Atoi(d.Val())
- if err != nil {
- return d.Errf("bad integer value '%s': %v", d.Val(), err)
- }
- if h.KeepAlive == nil {
- h.KeepAlive = new(KeepAlive)
- }
- h.KeepAlive.MaxIdleConns = num
+ case "keepalive_interval":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad interval value '%s': %v", d.Val(), err)
+ }
+ if h.KeepAlive == nil {
+ h.KeepAlive = new(KeepAlive)
+ }
+ h.KeepAlive.ProbeInterval = caddy.Duration(dur)
- case "keepalive_idle_conns_per_host":
- if !d.NextArg() {
- return d.ArgErr()
- }
- num, err := strconv.Atoi(d.Val())
- if err != nil {
- return d.Errf("bad integer value '%s': %v", d.Val(), err)
- }
- if h.KeepAlive == nil {
- h.KeepAlive = new(KeepAlive)
- }
- h.KeepAlive.MaxIdleConnsPerHost = num
+ case "keepalive_idle_conns":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ num, err := strconv.Atoi(d.Val())
+ if err != nil {
+ return d.Errf("bad integer value '%s': %v", d.Val(), err)
+ }
+ if h.KeepAlive == nil {
+ h.KeepAlive = new(KeepAlive)
+ }
+ h.KeepAlive.MaxIdleConns = num
- case "versions":
- h.Versions = d.RemainingArgs()
- if len(h.Versions) == 0 {
- return d.ArgErr()
- }
+ case "keepalive_idle_conns_per_host":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ num, err := strconv.Atoi(d.Val())
+ if err != nil {
+ return d.Errf("bad integer value '%s': %v", d.Val(), err)
+ }
+ if h.KeepAlive == nil {
+ h.KeepAlive = new(KeepAlive)
+ }
+ h.KeepAlive.MaxIdleConnsPerHost = num
- case "compression":
- if d.NextArg() {
- if d.Val() == "off" {
- var disable bool
- h.Compression = &disable
- }
- }
+ case "versions":
+ h.Versions = d.RemainingArgs()
+ if len(h.Versions) == 0 {
+ return d.ArgErr()
+ }
- case "max_conns_per_host":
- if !d.NextArg() {
- return d.ArgErr()
- }
- num, err := strconv.Atoi(d.Val())
- if err != nil {
- return d.Errf("bad integer value '%s': %v", d.Val(), err)
+ case "compression":
+ if d.NextArg() {
+ if d.Val() == "off" {
+ var disable bool
+ h.Compression = &disable
}
- h.MaxConnsPerHost = num
+ }
- default:
- return d.Errf("unrecognized subdirective %s", d.Val())
+ case "max_conns_per_host":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ num, err := strconv.Atoi(d.Val())
+ if err != nil {
+ return d.Errf("bad integer value '%s': %v", d.Val(), err)
}
+ h.MaxConnsPerHost = num
+
+ default:
+ return d.Errf("unrecognized subdirective %s", d.Val())
}
}
return nil
@@ -1241,25 +1240,25 @@ func parseCopyResponseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHan
// status <status>
// }
func (h *CopyResponseHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- args := d.RemainingArgs()
- if len(args) == 1 {
- if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
- h.StatusCode = caddyhttp.WeakString(args[0])
- break
- }
+ d.Next() // consume directive name
+
+ args := d.RemainingArgs()
+ if len(args) == 1 {
+ if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
+ h.StatusCode = caddyhttp.WeakString(args[0])
+ return nil
}
+ }
- for d.NextBlock(0) {
- switch d.Val() {
- case "status":
- if !d.NextArg() {
- return d.ArgErr()
- }
- h.StatusCode = caddyhttp.WeakString(d.Val())
- default:
- return d.Errf("unrecognized subdirective '%s'", d.Val())
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "status":
+ if !d.NextArg() {
+ return d.ArgErr()
}
+ h.StatusCode = caddyhttp.WeakString(d.Val())
+ default:
+ return d.Errf("unrecognized subdirective '%s'", d.Val())
}
}
return nil
@@ -1281,23 +1280,23 @@ func parseCopyResponseHeadersCaddyfile(h httpcaddyfile.Helper) (caddyhttp.Middle
// exclude <fields...>
// }
func (h *CopyResponseHeadersHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- args := d.RemainingArgs()
- if len(args) > 0 {
- return d.ArgErr()
- }
+ d.Next() // consume directive name
- for d.NextBlock(0) {
- switch d.Val() {
- case "include":
- h.Include = append(h.Include, d.RemainingArgs()...)
+ args := d.RemainingArgs()
+ if len(args) > 0 {
+ return d.ArgErr()
+ }
- case "exclude":
- h.Exclude = append(h.Exclude, d.RemainingArgs()...)
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "include":
+ h.Include = append(h.Include, d.RemainingArgs()...)
- default:
- return d.Errf("unrecognized subdirective '%s'", d.Val())
- }
+ case "exclude":
+ h.Exclude = append(h.Exclude, d.RemainingArgs()...)
+
+ default:
+ return d.Errf("unrecognized subdirective '%s'", d.Val())
}
}
return nil
@@ -1315,89 +1314,88 @@ func (h *CopyResponseHeadersHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser)
// dial_fallback_delay <timeout>
// }
func (u *SRVUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- args := d.RemainingArgs()
- if len(args) > 1 {
- return d.ArgErr()
- }
- if len(args) > 0 {
- u.Name = args[0]
- }
+ d.Next() // consume upstream source name
- for d.NextBlock(0) {
- switch d.Val() {
- case "service":
- if !d.NextArg() {
- return d.ArgErr()
- }
- if u.Service != "" {
- return d.Errf("srv service has already been specified")
- }
- u.Service = d.Val()
+ args := d.RemainingArgs()
+ if len(args) > 1 {
+ return d.ArgErr()
+ }
+ if len(args) > 0 {
+ u.Name = args[0]
+ }
- case "proto":
- if !d.NextArg() {
- return d.ArgErr()
- }
- if u.Proto != "" {
- return d.Errf("srv proto has already been specified")
- }
- u.Proto = d.Val()
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "service":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ if u.Service != "" {
+ return d.Errf("srv service has already been specified")
+ }
+ u.Service = d.Val()
- case "name":
- if !d.NextArg() {
- return d.ArgErr()
- }
- if u.Name != "" {
- return d.Errf("srv name has already been specified")
- }
- u.Name = d.Val()
+ case "proto":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ if u.Proto != "" {
+ return d.Errf("srv proto has already been specified")
+ }
+ u.Proto = d.Val()
- case "refresh":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("parsing refresh interval duration: %v", err)
- }
- u.Refresh = caddy.Duration(dur)
+ case "name":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ if u.Name != "" {
+ return d.Errf("srv name has already been specified")
+ }
+ u.Name = d.Val()
- case "resolvers":
- if u.Resolver == nil {
- u.Resolver = new(UpstreamResolver)
- }
- u.Resolver.Addresses = d.RemainingArgs()
- if len(u.Resolver.Addresses) == 0 {
- return d.Errf("must specify at least one resolver address")
- }
+ case "refresh":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("parsing refresh interval duration: %v", err)
+ }
+ u.Refresh = caddy.Duration(dur)
- case "dial_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
- }
- u.DialTimeout = caddy.Duration(dur)
+ case "resolvers":
+ if u.Resolver == nil {
+ u.Resolver = new(UpstreamResolver)
+ }
+ u.Resolver.Addresses = d.RemainingArgs()
+ if len(u.Resolver.Addresses) == 0 {
+ return d.Errf("must specify at least one resolver address")
+ }
- case "dial_fallback_delay":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad delay value '%s': %v", d.Val(), err)
- }
- u.FallbackDelay = caddy.Duration(dur)
+ case "dial_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
+ }
+ u.DialTimeout = caddy.Duration(dur)
- default:
- return d.Errf("unrecognized srv option '%s'", d.Val())
+ case "dial_fallback_delay":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad delay value '%s': %v", d.Val(), err)
}
+ u.FallbackDelay = caddy.Duration(dur)
+
+ default:
+ return d.Errf("unrecognized srv option '%s'", d.Val())
}
}
-
return nil
}
@@ -1413,105 +1411,104 @@ func (u *SRVUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
// versions ipv4|ipv6
// }
func (u *AUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- args := d.RemainingArgs()
- if len(args) > 2 {
- return d.ArgErr()
- }
- if len(args) > 0 {
- u.Name = args[0]
- if len(args) == 2 {
- u.Port = args[1]
- }
+ d.Next() // consume upstream source name
+
+ args := d.RemainingArgs()
+ if len(args) > 2 {
+ return d.ArgErr()
+ }
+ if len(args) > 0 {
+ u.Name = args[0]
+ if len(args) == 2 {
+ u.Port = args[1]
}
+ }
- for d.NextBlock(0) {
- switch d.Val() {
- case "name":
- if !d.NextArg() {
- return d.ArgErr()
- }
- if u.Name != "" {
- return d.Errf("a name has already been specified")
- }
- u.Name = d.Val()
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "name":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ if u.Name != "" {
+ return d.Errf("a name has already been specified")
+ }
+ u.Name = d.Val()
- case "port":
- if !d.NextArg() {
- return d.ArgErr()
- }
- if u.Port != "" {
- return d.Errf("a port has already been specified")
- }
- u.Port = d.Val()
+ case "port":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ if u.Port != "" {
+ return d.Errf("a port has already been specified")
+ }
+ u.Port = d.Val()
- case "refresh":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("parsing refresh interval duration: %v", err)
- }
- u.Refresh = caddy.Duration(dur)
+ case "refresh":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("parsing refresh interval duration: %v", err)
+ }
+ u.Refresh = caddy.Duration(dur)
- case "resolvers":
- if u.Resolver == nil {
- u.Resolver = new(UpstreamResolver)
- }
- u.Resolver.Addresses = d.RemainingArgs()
- if len(u.Resolver.Addresses) == 0 {
- return d.Errf("must specify at least one resolver address")
- }
+ case "resolvers":
+ if u.Resolver == nil {
+ u.Resolver = new(UpstreamResolver)
+ }
+ u.Resolver.Addresses = d.RemainingArgs()
+ if len(u.Resolver.Addresses) == 0 {
+ return d.Errf("must specify at least one resolver address")
+ }
- case "dial_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad timeout value '%s': %v", d.Val(), err)
- }
- u.DialTimeout = caddy.Duration(dur)
+ case "dial_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad timeout value '%s': %v", d.Val(), err)
+ }
+ u.DialTimeout = caddy.Duration(dur)
- case "dial_fallback_delay":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad delay value '%s': %v", d.Val(), err)
- }
- u.FallbackDelay = caddy.Duration(dur)
+ case "dial_fallback_delay":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad delay value '%s': %v", d.Val(), err)
+ }
+ u.FallbackDelay = caddy.Duration(dur)
- case "versions":
- args := d.RemainingArgs()
- if len(args) == 0 {
- return d.Errf("must specify at least one version")
- }
+ case "versions":
+ args := d.RemainingArgs()
+ if len(args) == 0 {
+ return d.Errf("must specify at least one version")
+ }
- if u.Versions == nil {
- u.Versions = &IPVersions{}
- }
+ if u.Versions == nil {
+ u.Versions = &IPVersions{}
+ }
- trueBool := true
- for _, arg := range args {
- switch arg {
- case "ipv4":
- u.Versions.IPv4 = &trueBool
- case "ipv6":
- u.Versions.IPv6 = &trueBool
- default:
- return d.Errf("unsupported version: '%s'", arg)
- }
+ trueBool := true
+ for _, arg := range args {
+ switch arg {
+ case "ipv4":
+ u.Versions.IPv4 = &trueBool
+ case "ipv6":
+ u.Versions.IPv6 = &trueBool
+ default:
+ return d.Errf("unsupported version: '%s'", arg)
}
-
- default:
- return d.Errf("unrecognized a option '%s'", d.Val())
}
+
+ default:
+ return d.Errf("unrecognized a option '%s'", d.Val())
}
}
-
return nil
}
@@ -1521,26 +1518,25 @@ func (u *AUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
// <source> [...]
// }
func (u *MultiUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume upstream source name
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- dynModule := d.Val()
- modID := "http.reverse_proxy.upstreams." + dynModule
- unm, err := caddyfile.UnmarshalModule(d, modID)
- if err != nil {
- return err
- }
- source, ok := unm.(UpstreamSource)
- if !ok {
- return d.Errf("module %s (%T) is not an UpstreamSource", modID, unm)
- }
- u.SourcesRaw = append(u.SourcesRaw, caddyconfig.JSONModuleObject(source, "source", dynModule, nil))
- }
+ if d.NextArg() {
+ return d.ArgErr()
}
+ for d.NextBlock(0) {
+ dynModule := d.Val()
+ modID := "http.reverse_proxy.upstreams." + dynModule
+ unm, err := caddyfile.UnmarshalModule(d, modID)
+ if err != nil {
+ return err
+ }
+ source, ok := unm.(UpstreamSource)
+ if !ok {
+ return d.Errf("module %s (%T) is not an UpstreamSource", modID, unm)
+ }
+ u.SourcesRaw = append(u.SourcesRaw, caddyconfig.JSONModuleObject(source, "source", dynModule, nil))
+ }
return nil
}
diff --git a/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go b/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go
index a24a3ed69..68eee32be 100644
--- a/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go
+++ b/modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go
@@ -46,76 +46,75 @@ func init() {
// capture_stderr
// }
func (t *Transport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- for d.NextBlock(0) {
- switch d.Val() {
- case "root":
- if !d.NextArg() {
- return d.ArgErr()
- }
- t.Root = d.Val()
-
- case "split":
- t.SplitPath = d.RemainingArgs()
- if len(t.SplitPath) == 0 {
- return d.ArgErr()
- }
+ d.Next() // consume transport name
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "root":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ t.Root = d.Val()
- case "env":
- args := d.RemainingArgs()
- if len(args) != 2 {
- return d.ArgErr()
- }
- if t.EnvVars == nil {
- t.EnvVars = make(map[string]string)
- }
- t.EnvVars[args[0]] = args[1]
+ case "split":
+ t.SplitPath = d.RemainingArgs()
+ if len(t.SplitPath) == 0 {
+ return d.ArgErr()
+ }
- case "resolve_root_symlink":
- if d.NextArg() {
- return d.ArgErr()
- }
- t.ResolveRootSymlink = true
+ case "env":
+ args := d.RemainingArgs()
+ if len(args) != 2 {
+ return d.ArgErr()
+ }
+ if t.EnvVars == nil {
+ t.EnvVars = make(map[string]string)
+ }
+ t.EnvVars[args[0]] = args[1]
- case "dial_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad timeout value %s: %v", d.Val(), err)
- }
- t.DialTimeout = caddy.Duration(dur)
+ case "resolve_root_symlink":
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+ t.ResolveRootSymlink = true
- case "read_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad timeout value %s: %v", d.Val(), err)
- }
- t.ReadTimeout = caddy.Duration(dur)
+ case "dial_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad timeout value %s: %v", d.Val(), err)
+ }
+ t.DialTimeout = caddy.Duration(dur)
- case "write_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("bad timeout value %s: %v", d.Val(), err)
- }
- t.WriteTimeout = caddy.Duration(dur)
+ case "read_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad timeout value %s: %v", d.Val(), err)
+ }
+ t.ReadTimeout = caddy.Duration(dur)
- case "capture_stderr":
- if d.NextArg() {
- return d.ArgErr()
- }
- t.CaptureStderr = true
+ case "write_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("bad timeout value %s: %v", d.Val(), err)
+ }
+ t.WriteTimeout = caddy.Duration(dur)
- default:
- return d.Errf("unrecognized subdirective %s", d.Val())
+ case "capture_stderr":
+ if d.NextArg() {
+ return d.ArgErr()
}
+ t.CaptureStderr = true
+
+ default:
+ return d.Errf("unrecognized subdirective %s", d.Val())
}
}
return nil
diff --git a/modules/caddyhttp/reverseproxy/selectionpolicies.go b/modules/caddyhttp/reverseproxy/selectionpolicies.go
index acb069a74..b56c8074c 100644
--- a/modules/caddyhttp/reverseproxy/selectionpolicies.go
+++ b/modules/caddyhttp/reverseproxy/selectionpolicies.go
@@ -68,10 +68,9 @@ func (r RandomSelection) Select(pool UpstreamPool, request *http.Request, _ http
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *RandomSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume policy name
+ if d.NextArg() {
+ return d.ArgErr()
}
return nil
}
@@ -98,22 +97,22 @@ func (WeightedRoundRobinSelection) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *WeightedRoundRobinSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- args := d.RemainingArgs()
- if len(args) == 0 {
- return d.ArgErr()
- }
+ d.Next() // consume policy name
- for _, weight := range args {
- weightInt, err := strconv.Atoi(weight)
- if err != nil {
- return d.Errf("invalid weight value '%s': %v", weight, err)
- }
- if weightInt < 1 {
- return d.Errf("invalid weight value '%s': weight should be non-zero and positive", weight)
- }
- r.Weights = append(r.Weights, weightInt)
+ args := d.RemainingArgs()
+ if len(args) == 0 {
+ return d.ArgErr()
+ }
+
+ for _, weight := range args {
+ weightInt, err := strconv.Atoi(weight)
+ if err != nil {
+ return d.Errf("invalid weight value '%s': %v", weight, err)
+ }
+ if weightInt < 1 {
+ return d.Errf("invalid weight value '%s': weight should be non-zero and positive", weight)
}
+ r.Weights = append(r.Weights, weightInt)
}
return nil
}
@@ -179,17 +178,17 @@ func (RandomChoiceSelection) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *RandomChoiceSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if !d.NextArg() {
- return d.ArgErr()
- }
- chooseStr := d.Val()
- choose, err := strconv.Atoi(chooseStr)
- if err != nil {
- return d.Errf("invalid choice value '%s': %v", chooseStr, err)
- }
- r.Choose = choose
+ d.Next() // consume policy name
+
+ if !d.NextArg() {
+ return d.ArgErr()
}
+ chooseStr := d.Val()
+ choose, err := strconv.Atoi(chooseStr)
+ if err != nil {
+ return d.Errf("invalid choice value '%s': %v", chooseStr, err)
+ }
+ r.Choose = choose
return nil
}
@@ -280,10 +279,9 @@ func (LeastConnSelection) Select(pool UpstreamPool, _ *http.Request, _ http.Resp
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *LeastConnSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume policy name
+ if d.NextArg() {
+ return d.ArgErr()
}
return nil
}
@@ -320,10 +318,9 @@ func (r *RoundRobinSelection) Select(pool UpstreamPool, _ *http.Request, _ http.
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *RoundRobinSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume policy name
+ if d.NextArg() {
+ return d.ArgErr()
}
return nil
}
@@ -352,10 +349,9 @@ func (FirstSelection) Select(pool UpstreamPool, _ *http.Request, _ http.Response
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *FirstSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume policy name
+ if d.NextArg() {
+ return d.ArgErr()
}
return nil
}
@@ -383,10 +379,9 @@ func (IPHashSelection) Select(pool UpstreamPool, req *http.Request, _ http.Respo
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *IPHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume policy name
+ if d.NextArg() {
+ return d.ArgErr()
}
return nil
}
@@ -416,10 +411,9 @@ func (ClientIPHashSelection) Select(pool UpstreamPool, req *http.Request, _ http
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *ClientIPHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume policy name
+ if d.NextArg() {
+ return d.ArgErr()
}
return nil
}
@@ -443,10 +437,9 @@ func (URIHashSelection) Select(pool UpstreamPool, req *http.Request, _ http.Resp
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *URIHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume policy name
+ if d.NextArg() {
+ return d.ArgErr()
}
return nil
}
@@ -504,13 +497,14 @@ func (s QueryHashSelection) Select(pool UpstreamPool, req *http.Request, _ http.
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (s *QueryHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if !d.NextArg() {
- return d.ArgErr()
- }
- s.Key = d.Val()
+ d.Next() // consume policy name
+
+ if !d.NextArg() {
+ return d.ArgErr()
}
- for nesting := d.Nesting(); d.NextBlock(nesting); {
+ s.Key = d.Val()
+
+ for d.NextBlock(0) {
switch d.Val() {
case "fallback":
if !d.NextArg() {
@@ -583,13 +577,14 @@ func (s HeaderHashSelection) Select(pool UpstreamPool, req *http.Request, _ http
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (s *HeaderHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if !d.NextArg() {
- return d.ArgErr()
- }
- s.Field = d.Val()
+ d.Next() // consume policy name
+
+ if !d.NextArg() {
+ return d.ArgErr()
}
- for nesting := d.Nesting(); d.NextBlock(nesting); {
+ s.Field = d.Val()
+
+ for d.NextBlock(0) {
switch d.Val() {
case "fallback":
if !d.NextArg() {
@@ -708,7 +703,7 @@ func (s *CookieHashSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
default:
return d.ArgErr()
}
- for nesting := d.Nesting(); d.NextBlock(nesting); {
+ for d.NextBlock(0) {
switch d.Val() {
case "fallback":
if !d.NextArg() {
diff --git a/modules/caddyhttp/rewrite/caddyfile.go b/modules/caddyhttp/rewrite/caddyfile.go
index 5d7bd32e6..363dbfdb5 100644
--- a/modules/caddyhttp/rewrite/caddyfile.go
+++ b/modules/caddyhttp/rewrite/caddyfile.go
@@ -39,10 +39,7 @@ func init() {
// Only URI components which are given in <to> will be set in the resulting URI.
// See the docs for the rewrite handler for more information.
func parseCaddyfileRewrite(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
- // consume directive name
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
+ h.Next() // consume directive name
// count the tokens to determine what to do
argsCount := h.CountRemainingArgs()
@@ -66,26 +63,9 @@ func parseCaddyfileRewrite(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue,
if err != nil {
return nil, err
}
+ h.Next() // consume directive name again, matcher parsing does a reset
+ h.Next() // advance to the rewrite URI
- // consume directive name, again, because extracting matcher does a reset
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- // advance to the rewrite URI
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
-
- var rewr Rewrite
- for h.Next() {
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- rewr.URI = h.Val()
- if h.NextArg() {
- return nil, h.ArgErr()
- }
- }
return h.NewRoute(userMatcherSet, Rewrite{URI: h.Val()}), nil
}
@@ -93,17 +73,14 @@ func parseCaddyfileRewrite(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue,
//
// method [<matcher>] <method>
func parseCaddyfileMethod(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
- var rewr Rewrite
- for h.Next() {
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
- rewr.Method = h.Val()
- if h.NextArg() {
- return nil, h.ArgErr()
- }
+ h.Next() // consume directive name
+ if !h.NextArg() {
+ return nil, h.ArgErr()
}
- return rewr, nil
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ return Rewrite{Method: h.Val()}, nil
}
// parseCaddyfileURI sets up a handler for manipulating (but not "rewriting") the
@@ -118,65 +95,71 @@ func parseCaddyfileMethod(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler,
// path_regexp is used, then regular expression replacements will be performed
// on the path portion of the URI (and a limit cannot be set).
func parseCaddyfileURI(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
+ h.Next() // consume directive name
+
+ args := h.RemainingArgs()
+ if len(args) < 2 {
+ return nil, h.ArgErr()
+ }
+
var rewr Rewrite
- for h.Next() {
- args := h.RemainingArgs()
- if len(args) < 2 {
+
+ switch args[0] {
+ case "strip_prefix":
+ if len(args) > 2 {
return nil, h.ArgErr()
}
- switch args[0] {
- case "strip_prefix":
- if len(args) > 2 {
- return nil, h.ArgErr()
- }
- rewr.StripPathPrefix = args[1]
- if !strings.HasPrefix(rewr.StripPathPrefix, "/") {
- rewr.StripPathPrefix = "/" + rewr.StripPathPrefix
- }
- case "strip_suffix":
- if len(args) > 2 {
- return nil, h.ArgErr()
- }
- rewr.StripPathSuffix = args[1]
- case "replace":
- var find, replace, lim string
- switch len(args) {
- case 4:
- lim = args[3]
- fallthrough
- case 3:
- find = args[1]
- replace = args[2]
- default:
- return nil, h.ArgErr()
- }
+ rewr.StripPathPrefix = args[1]
+ if !strings.HasPrefix(rewr.StripPathPrefix, "/") {
+ rewr.StripPathPrefix = "/" + rewr.StripPathPrefix
+ }
- var limInt int
- if lim != "" {
- var err error
- limInt, err = strconv.Atoi(lim)
- if err != nil {
- return nil, h.Errf("limit must be an integer; invalid: %v", err)
- }
- }
+ case "strip_suffix":
+ if len(args) > 2 {
+ return nil, h.ArgErr()
+ }
+ rewr.StripPathSuffix = args[1]
+
+ case "replace":
+ var find, replace, lim string
+ switch len(args) {
+ case 4:
+ lim = args[3]
+ fallthrough
+ case 3:
+ find = args[1]
+ replace = args[2]
+ default:
+ return nil, h.ArgErr()
+ }
- rewr.URISubstring = append(rewr.URISubstring, substrReplacer{
- Find: find,
- Replace: replace,
- Limit: limInt,
- })
- case "path_regexp":
- if len(args) != 3 {
- return nil, h.ArgErr()
+ var limInt int
+ if lim != "" {
+ var err error
+ limInt, err = strconv.Atoi(lim)
+ if err != nil {
+ return nil, h.Errf("limit must be an integer; invalid: %v", err)
}
- find, replace := args[1], args[2]
- rewr.PathRegexp = append(rewr.PathRegexp, &regexReplacer{
- Find: find,
- Replace: replace,
- })
- default:
- return nil, h.Errf("unrecognized URI manipulation '%s'", args[0])
}
+
+ rewr.URISubstring = append(rewr.URISubstring, substrReplacer{
+ Find: find,
+ Replace: replace,
+ Limit: limInt,
+ })
+
+ case "path_regexp":
+ if len(args) != 3 {
+ return nil, h.ArgErr()
+ }
+ find, replace := args[1], args[2]
+ rewr.PathRegexp = append(rewr.PathRegexp, &regexReplacer{
+ Find: find,
+ Replace: replace,
+ })
+
+ default:
+ return nil, h.Errf("unrecognized URI manipulation '%s'", args[0])
}
return rewr, nil
}
@@ -190,9 +173,9 @@ func parseCaddyfileURI(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, err
// Only path matchers (with a `/` prefix) are supported as this is a shortcut
// for the handle directive with a strip_prefix rewrite.
func parseCaddyfileHandlePath(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
- if !h.Next() {
- return nil, h.ArgErr()
- }
+ h.Next() // consume directive name
+
+ // there must be a path matcher
if !h.NextArg() {
return nil, h.ArgErr()
}
diff --git a/modules/caddyhttp/staticerror.go b/modules/caddyhttp/staticerror.go
index 7cf1a3e95..b6e10ff32 100644
--- a/modules/caddyhttp/staticerror.go
+++ b/modules/caddyhttp/staticerror.go
@@ -60,36 +60,35 @@ func (StaticError) CaddyModule() caddy.ModuleInfo {
// If there is just one argument (other than the matcher), it is considered
// to be a status code if it's a valid positive integer of 3 digits.
func (e *StaticError) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- args := d.RemainingArgs()
- switch len(args) {
- case 1:
- if len(args[0]) == 3 {
- if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
- e.StatusCode = WeakString(args[0])
- break
- }
+ d.Next() // consume directive name
+ args := d.RemainingArgs()
+ switch len(args) {
+ case 1:
+ if len(args[0]) == 3 {
+ if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
+ e.StatusCode = WeakString(args[0])
+ break
}
- e.Error = args[0]
- case 2:
- e.Error = args[0]
- e.StatusCode = WeakString(args[1])
- default:
- return d.ArgErr()
}
+ e.Error = args[0]
+ case 2:
+ e.Error = args[0]
+ e.StatusCode = WeakString(args[1])
+ default:
+ return d.ArgErr()
+ }
- for d.NextBlock(0) {
- switch d.Val() {
- case "message":
- if e.Error != "" {
- return d.Err("message already specified")
- }
- if !d.AllArgs(&e.Error) {
- return d.ArgErr()
- }
- default:
- return d.Errf("unrecognized subdirective '%s'", d.Val())
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "message":
+ if e.Error != "" {
+ return d.Err("message already specified")
}
+ if !d.AllArgs(&e.Error) {
+ return d.ArgErr()
+ }
+ default:
+ return d.Errf("unrecognized subdirective '%s'", d.Val())
}
}
return nil
diff --git a/modules/caddyhttp/staticresp.go b/modules/caddyhttp/staticresp.go
index d6befd689..3ec76f29f 100644
--- a/modules/caddyhttp/staticresp.go
+++ b/modules/caddyhttp/staticresp.go
@@ -138,41 +138,40 @@ func (StaticResponse) CaddyModule() caddy.ModuleInfo {
// If there is just one argument (other than the matcher), it is considered
// to be a status code if it's a valid positive integer of 3 digits.
func (s *StaticResponse) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- args := d.RemainingArgs()
- switch len(args) {
- case 1:
- if len(args[0]) == 3 {
- if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
- s.StatusCode = WeakString(args[0])
- break
- }
+ d.Next() // consume directive name
+ args := d.RemainingArgs()
+ switch len(args) {
+ case 1:
+ if len(args[0]) == 3 {
+ if num, err := strconv.Atoi(args[0]); err == nil && num > 0 {
+ s.StatusCode = WeakString(args[0])
+ break
}
- s.Body = args[0]
- case 2:
- s.Body = args[0]
- s.StatusCode = WeakString(args[1])
- default:
- return d.ArgErr()
}
+ s.Body = args[0]
+ case 2:
+ s.Body = args[0]
+ s.StatusCode = WeakString(args[1])
+ default:
+ return d.ArgErr()
+ }
- for d.NextBlock(0) {
- switch d.Val() {
- case "body":
- if s.Body != "" {
- return d.Err("body already specified")
- }
- if !d.AllArgs(&s.Body) {
- return d.ArgErr()
- }
- case "close":
- if s.Close {
- return d.Err("close already specified")
- }
- s.Close = true
- default:
- return d.Errf("unrecognized subdirective '%s'", d.Val())
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "body":
+ if s.Body != "" {
+ return d.Err("body already specified")
+ }
+ if !d.AllArgs(&s.Body) {
+ return d.ArgErr()
}
+ case "close":
+ if s.Close {
+ return d.Err("close already specified")
+ }
+ s.Close = true
+ default:
+ return d.Errf("unrecognized subdirective '%s'", d.Val())
}
}
return nil
diff --git a/modules/caddyhttp/templates/caddyfile.go b/modules/caddyhttp/templates/caddyfile.go
index c3039aa89..d23493483 100644
--- a/modules/caddyhttp/templates/caddyfile.go
+++ b/modules/caddyhttp/templates/caddyfile.go
@@ -34,47 +34,46 @@ func init() {
// root <path>
// }
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
+ h.Next() // consume directive name
t := new(Templates)
- for h.Next() {
- for h.NextBlock(0) {
- switch h.Val() {
- case "mime":
- t.MIMETypes = h.RemainingArgs()
- if len(t.MIMETypes) == 0 {
- return nil, h.ArgErr()
- }
- case "between":
- t.Delimiters = h.RemainingArgs()
- if len(t.Delimiters) != 2 {
- return nil, h.ArgErr()
- }
- case "root":
- if !h.Args(&t.FileRoot) {
- return nil, h.ArgErr()
- }
- case "extensions":
- if h.NextArg() {
- return nil, h.ArgErr()
+ for h.NextBlock(0) {
+ switch h.Val() {
+ case "mime":
+ t.MIMETypes = h.RemainingArgs()
+ if len(t.MIMETypes) == 0 {
+ return nil, h.ArgErr()
+ }
+ case "between":
+ t.Delimiters = h.RemainingArgs()
+ if len(t.Delimiters) != 2 {
+ return nil, h.ArgErr()
+ }
+ case "root":
+ if !h.Args(&t.FileRoot) {
+ return nil, h.ArgErr()
+ }
+ case "extensions":
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ if t.ExtensionsRaw != nil {
+ return nil, h.Err("extensions already specified")
+ }
+ for nesting := h.Nesting(); h.NextBlock(nesting); {
+ extensionModuleName := h.Val()
+ modID := "http.handlers.templates.functions." + extensionModuleName
+ unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
+ if err != nil {
+ return nil, err
}
- if t.ExtensionsRaw != nil {
- return nil, h.Err("extensions already specified")
+ cf, ok := unm.(CustomFunctions)
+ if !ok {
+ return nil, h.Errf("module %s (%T) does not provide template functions", modID, unm)
}
- for nesting := h.Nesting(); h.NextBlock(nesting); {
- extensionModuleName := h.Val()
- modID := "http.handlers.templates.functions." + extensionModuleName
- unm, err := caddyfile.UnmarshalModule(h.Dispenser, modID)
- if err != nil {
- return nil, err
- }
- cf, ok := unm.(CustomFunctions)
- if !ok {
- return nil, h.Errf("module %s (%T) does not provide template functions", modID, unm)
- }
- if t.ExtensionsRaw == nil {
- t.ExtensionsRaw = make(caddy.ModuleMap)
- }
- t.ExtensionsRaw[extensionModuleName] = caddyconfig.JSON(cf, nil)
+ if t.ExtensionsRaw == nil {
+ t.ExtensionsRaw = make(caddy.ModuleMap)
}
+ t.ExtensionsRaw[extensionModuleName] = caddyconfig.JSON(cf, nil)
}
}
}
diff --git a/modules/caddyhttp/tracing/module.go b/modules/caddyhttp/tracing/module.go
index fd117c537..85fd63002 100644
--- a/modules/caddyhttp/tracing/module.go
+++ b/modules/caddyhttp/tracing/module.go
@@ -88,20 +88,18 @@ func (ot *Tracing) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
"span": &ot.SpanName,
}
- for d.Next() {
- args := d.RemainingArgs()
- if len(args) > 0 {
- return d.ArgErr()
- }
+ d.Next() // consume directive name
+ if d.NextArg() {
+ return d.ArgErr()
+ }
- for d.NextBlock(0) {
- if dst, ok := paramsMap[d.Val()]; ok {
- if err := setParameter(d, dst); err != nil {
- return err
- }
- } else {
- return d.ArgErr()
+ for d.NextBlock(0) {
+ if dst, ok := paramsMap[d.Val()]; ok {
+ if err := setParameter(d, dst); err != nil {
+ return err
}
+ } else {
+ return d.ArgErr()
}
}
return nil
diff --git a/modules/caddyhttp/vars.go b/modules/caddyhttp/vars.go
index d2d7f62c5..917a15051 100644
--- a/modules/caddyhttp/vars.go
+++ b/modules/caddyhttp/vars.go
@@ -68,6 +68,8 @@ func (m VarsMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next H
// ...
// }
func (m *VarsMiddleware) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
+ d.Next() // consume directive name
+
if *m == nil {
*m = make(VarsMiddleware)
}
@@ -94,15 +96,13 @@ func (m *VarsMiddleware) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return nil
}
- for d.Next() {
- if err := nextVar(true); err != nil {
+ if err := nextVar(true); err != nil {
+ return err
+ }
+ for d.NextBlock(0) {
+ if err := nextVar(false); err != nil {
return err
}
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- if err := nextVar(false); err != nil {
- return err
- }
- }
}
return nil
@@ -135,6 +135,7 @@ func (m *VarsMatcher) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if *m == nil {
*m = make(map[string][]string)
}
+ // iterate to merge multiple matchers into one
for d.Next() {
var field string
if !d.Args(&field) {
@@ -216,6 +217,7 @@ func (m *MatchVarsRE) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if *m == nil {
*m = make(map[string]*MatchRegexp)
}
+ // iterate to merge multiple matchers into one
for d.Next() {
var first, second, third string
if !d.Args(&first, &second) {
diff --git a/modules/caddypki/acmeserver/caddyfile.go b/modules/caddypki/acmeserver/caddyfile.go
index 3b52113b5..51290eba6 100644
--- a/modules/caddypki/acmeserver/caddyfile.go
+++ b/modules/caddypki/acmeserver/caddyfile.go
@@ -34,53 +34,52 @@ func init() {
// resolvers <addresses...>
// }
func parseACMEServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
- if !h.Next() {
- return nil, h.ArgErr()
- }
-
+ h.Next() // consume directive name
matcherSet, err := h.ExtractMatcherSet()
if err != nil {
return nil, err
}
+ h.Next() // consume the directive name again (matcher parsing resets)
+
+ // no inline args allowed
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
var acmeServer Handler
var ca *caddypki.CA
- for h.Next() {
- if h.NextArg() {
- return nil, h.ArgErr()
- }
- for h.NextBlock(0) {
- switch h.Val() {
- case "ca":
- if !h.AllArgs(&acmeServer.CA) {
- return nil, h.ArgErr()
- }
- if ca == nil {
- ca = new(caddypki.CA)
- }
- ca.ID = acmeServer.CA
- case "lifetime":
- if !h.NextArg() {
- return nil, h.ArgErr()
- }
-
- dur, err := caddy.ParseDuration(h.Val())
- if err != nil {
- return nil, err
- }
-
- if d := time.Duration(ca.IntermediateLifetime); d > 0 && dur > d {
- return nil, h.Errf("certificate lifetime (%s) exceeds intermediate certificate lifetime (%s)", dur, d)
- }
-
- acmeServer.Lifetime = caddy.Duration(dur)
-
- case "resolvers":
- acmeServer.Resolvers = h.RemainingArgs()
- if len(acmeServer.Resolvers) == 0 {
- return nil, h.Errf("must specify at least one resolver address")
- }
+ for h.NextBlock(0) {
+ switch h.Val() {
+ case "ca":
+ if !h.AllArgs(&acmeServer.CA) {
+ return nil, h.ArgErr()
+ }
+ if ca == nil {
+ ca = new(caddypki.CA)
+ }
+ ca.ID = acmeServer.CA
+
+ case "lifetime":
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+
+ dur, err := caddy.ParseDuration(h.Val())
+ if err != nil {
+ return nil, err
+ }
+
+ if d := time.Duration(ca.IntermediateLifetime); d > 0 && dur > d {
+ return nil, h.Errf("certificate lifetime (%s) exceeds intermediate certificate lifetime (%s)", dur, d)
+ }
+
+ acmeServer.Lifetime = caddy.Duration(dur)
+
+ case "resolvers":
+ acmeServer.Resolvers = h.RemainingArgs()
+ if len(acmeServer.Resolvers) == 0 {
+ return nil, h.Errf("must specify at least one resolver address")
}
}
}
diff --git a/modules/caddytls/acmeissuer.go b/modules/caddytls/acmeissuer.go
index a7dbd26ec..036e79b1b 100644
--- a/modules/caddytls/acmeissuer.go
+++ b/modules/caddytls/acmeissuer.go
@@ -277,218 +277,219 @@ func (iss *ACMEIssuer) GetACMEIssuer() *ACMEIssuer { return iss }
// }
// }
func (iss *ACMEIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
+ d.Next() // consume issuer name
+
+ if d.NextArg() {
+ iss.CA = d.Val()
if d.NextArg() {
- iss.CA = d.Val()
- if d.NextArg() {
- return d.ArgErr()
- }
+ return d.ArgErr()
}
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "dir":
- if iss.CA != "" {
- return d.Errf("directory is already specified: %s", iss.CA)
- }
- if !d.AllArgs(&iss.CA) {
- return d.ArgErr()
- }
-
- case "test_dir":
- if !d.AllArgs(&iss.TestCA) {
- return d.ArgErr()
- }
+ }
- case "email":
- if !d.AllArgs(&iss.Email) {
- return d.ArgErr()
- }
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "dir":
+ if iss.CA != "" {
+ return d.Errf("directory is already specified: %s", iss.CA)
+ }
+ if !d.AllArgs(&iss.CA) {
+ return d.ArgErr()
+ }
- case "timeout":
- var timeoutStr string
- if !d.AllArgs(&timeoutStr) {
- return d.ArgErr()
- }
- timeout, err := caddy.ParseDuration(timeoutStr)
- if err != nil {
- return d.Errf("invalid timeout duration %s: %v", timeoutStr, err)
- }
- iss.ACMETimeout = caddy.Duration(timeout)
+ case "test_dir":
+ if !d.AllArgs(&iss.TestCA) {
+ return d.ArgErr()
+ }
- case "disable_http_challenge":
- if d.NextArg() {
- return d.ArgErr()
- }
- if iss.Challenges == nil {
- iss.Challenges = new(ChallengesConfig)
- }
- if iss.Challenges.HTTP == nil {
- iss.Challenges.HTTP = new(HTTPChallengeConfig)
- }
- iss.Challenges.HTTP.Disabled = true
+ case "email":
+ if !d.AllArgs(&iss.Email) {
+ return d.ArgErr()
+ }
- case "disable_tlsalpn_challenge":
- if d.NextArg() {
- return d.ArgErr()
- }
- if iss.Challenges == nil {
- iss.Challenges = new(ChallengesConfig)
- }
- if iss.Challenges.TLSALPN == nil {
- iss.Challenges.TLSALPN = new(TLSALPNChallengeConfig)
- }
- iss.Challenges.TLSALPN.Disabled = true
+ case "timeout":
+ var timeoutStr string
+ if !d.AllArgs(&timeoutStr) {
+ return d.ArgErr()
+ }
+ timeout, err := caddy.ParseDuration(timeoutStr)
+ if err != nil {
+ return d.Errf("invalid timeout duration %s: %v", timeoutStr, err)
+ }
+ iss.ACMETimeout = caddy.Duration(timeout)
- case "alt_http_port":
- if !d.NextArg() {
- return d.ArgErr()
- }
- port, err := strconv.Atoi(d.Val())
- if err != nil {
- return d.Errf("invalid port %s: %v", d.Val(), err)
- }
- if iss.Challenges == nil {
- iss.Challenges = new(ChallengesConfig)
- }
- if iss.Challenges.HTTP == nil {
- iss.Challenges.HTTP = new(HTTPChallengeConfig)
- }
- iss.Challenges.HTTP.AlternatePort = port
+ case "disable_http_challenge":
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+ if iss.Challenges == nil {
+ iss.Challenges = new(ChallengesConfig)
+ }
+ if iss.Challenges.HTTP == nil {
+ iss.Challenges.HTTP = new(HTTPChallengeConfig)
+ }
+ iss.Challenges.HTTP.Disabled = true
- case "alt_tlsalpn_port":
- if !d.NextArg() {
- return d.ArgErr()
- }
- port, err := strconv.Atoi(d.Val())
- if err != nil {
- return d.Errf("invalid port %s: %v", d.Val(), err)
- }
- if iss.Challenges == nil {
- iss.Challenges = new(ChallengesConfig)
- }
- if iss.Challenges.TLSALPN == nil {
- iss.Challenges.TLSALPN = new(TLSALPNChallengeConfig)
- }
- iss.Challenges.TLSALPN.AlternatePort = port
+ case "disable_tlsalpn_challenge":
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+ if iss.Challenges == nil {
+ iss.Challenges = new(ChallengesConfig)
+ }
+ if iss.Challenges.TLSALPN == nil {
+ iss.Challenges.TLSALPN = new(TLSALPNChallengeConfig)
+ }
+ iss.Challenges.TLSALPN.Disabled = true
- case "eab":
- iss.ExternalAccount = new(acme.EAB)
- if !d.AllArgs(&iss.ExternalAccount.KeyID, &iss.ExternalAccount.MACKey) {
- return d.ArgErr()
- }
+ case "alt_http_port":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ port, err := strconv.Atoi(d.Val())
+ if err != nil {
+ return d.Errf("invalid port %s: %v", d.Val(), err)
+ }
+ if iss.Challenges == nil {
+ iss.Challenges = new(ChallengesConfig)
+ }
+ if iss.Challenges.HTTP == nil {
+ iss.Challenges.HTTP = new(HTTPChallengeConfig)
+ }
+ iss.Challenges.HTTP.AlternatePort = port
- case "trusted_roots":
- iss.TrustedRootsPEMFiles = d.RemainingArgs()
+ case "alt_tlsalpn_port":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ port, err := strconv.Atoi(d.Val())
+ if err != nil {
+ return d.Errf("invalid port %s: %v", d.Val(), err)
+ }
+ if iss.Challenges == nil {
+ iss.Challenges = new(ChallengesConfig)
+ }
+ if iss.Challenges.TLSALPN == nil {
+ iss.Challenges.TLSALPN = new(TLSALPNChallengeConfig)
+ }
+ iss.Challenges.TLSALPN.AlternatePort = port
- case "dns":
- if !d.NextArg() {
- return d.ArgErr()
- }
- provName := d.Val()
- if iss.Challenges == nil {
- iss.Challenges = new(ChallengesConfig)
- }
- if iss.Challenges.DNS == nil {
- iss.Challenges.DNS = new(DNSChallengeConfig)
- }
- unm, err := caddyfile.UnmarshalModule(d, "dns.providers."+provName)
- if err != nil {
- return err
- }
- iss.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, nil)
+ case "eab":
+ iss.ExternalAccount = new(acme.EAB)
+ if !d.AllArgs(&iss.ExternalAccount.KeyID, &iss.ExternalAccount.MACKey) {
+ return d.ArgErr()
+ }
- case "propagation_delay":
- if !d.NextArg() {
- return d.ArgErr()
- }
- delayStr := d.Val()
- delay, err := caddy.ParseDuration(delayStr)
- if err != nil {
- return d.Errf("invalid propagation_delay duration %s: %v", delayStr, err)
- }
- if iss.Challenges == nil {
- iss.Challenges = new(ChallengesConfig)
- }
- if iss.Challenges.DNS == nil {
- iss.Challenges.DNS = new(DNSChallengeConfig)
- }
- iss.Challenges.DNS.PropagationDelay = caddy.Duration(delay)
+ case "trusted_roots":
+ iss.TrustedRootsPEMFiles = d.RemainingArgs()
- case "propagation_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- timeoutStr := d.Val()
- var timeout time.Duration
- if timeoutStr == "-1" {
- timeout = time.Duration(-1)
- } else {
- var err error
- timeout, err = caddy.ParseDuration(timeoutStr)
- if err != nil {
- return d.Errf("invalid propagation_timeout duration %s: %v", timeoutStr, err)
- }
- }
- if iss.Challenges == nil {
- iss.Challenges = new(ChallengesConfig)
- }
- if iss.Challenges.DNS == nil {
- iss.Challenges.DNS = new(DNSChallengeConfig)
- }
- iss.Challenges.DNS.PropagationTimeout = caddy.Duration(timeout)
+ case "dns":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ provName := d.Val()
+ if iss.Challenges == nil {
+ iss.Challenges = new(ChallengesConfig)
+ }
+ if iss.Challenges.DNS == nil {
+ iss.Challenges.DNS = new(DNSChallengeConfig)
+ }
+ unm, err := caddyfile.UnmarshalModule(d, "dns.providers."+provName)
+ if err != nil {
+ return err
+ }
+ iss.Challenges.DNS.ProviderRaw = caddyconfig.JSONModuleObject(unm, "name", provName, nil)
- case "resolvers":
- if iss.Challenges == nil {
- iss.Challenges = new(ChallengesConfig)
- }
- if iss.Challenges.DNS == nil {
- iss.Challenges.DNS = new(DNSChallengeConfig)
- }
- iss.Challenges.DNS.Resolvers = d.RemainingArgs()
- if len(iss.Challenges.DNS.Resolvers) == 0 {
- return d.ArgErr()
- }
+ case "propagation_delay":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ delayStr := d.Val()
+ delay, err := caddy.ParseDuration(delayStr)
+ if err != nil {
+ return d.Errf("invalid propagation_delay duration %s: %v", delayStr, err)
+ }
+ if iss.Challenges == nil {
+ iss.Challenges = new(ChallengesConfig)
+ }
+ if iss.Challenges.DNS == nil {
+ iss.Challenges.DNS = new(DNSChallengeConfig)
+ }
+ iss.Challenges.DNS.PropagationDelay = caddy.Duration(delay)
- case "dns_ttl":
- if !d.NextArg() {
- return d.ArgErr()
- }
- ttlStr := d.Val()
- ttl, err := caddy.ParseDuration(ttlStr)
+ case "propagation_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ timeoutStr := d.Val()
+ var timeout time.Duration
+ if timeoutStr == "-1" {
+ timeout = time.Duration(-1)
+ } else {
+ var err error
+ timeout, err = caddy.ParseDuration(timeoutStr)
if err != nil {
- return d.Errf("invalid dns_ttl duration %s: %v", ttlStr, err)
- }
- if iss.Challenges == nil {
- iss.Challenges = new(ChallengesConfig)
+ return d.Errf("invalid propagation_timeout duration %s: %v", timeoutStr, err)
}
- if iss.Challenges.DNS == nil {
- iss.Challenges.DNS = new(DNSChallengeConfig)
- }
- iss.Challenges.DNS.TTL = caddy.Duration(ttl)
+ }
+ if iss.Challenges == nil {
+ iss.Challenges = new(ChallengesConfig)
+ }
+ if iss.Challenges.DNS == nil {
+ iss.Challenges.DNS = new(DNSChallengeConfig)
+ }
+ iss.Challenges.DNS.PropagationTimeout = caddy.Duration(timeout)
- case "dns_challenge_override_domain":
- arg := d.RemainingArgs()
- if len(arg) != 1 {
- return d.ArgErr()
- }
- if iss.Challenges == nil {
- iss.Challenges = new(ChallengesConfig)
- }
- if iss.Challenges.DNS == nil {
- iss.Challenges.DNS = new(DNSChallengeConfig)
- }
- iss.Challenges.DNS.OverrideDomain = arg[0]
+ case "resolvers":
+ if iss.Challenges == nil {
+ iss.Challenges = new(ChallengesConfig)
+ }
+ if iss.Challenges.DNS == nil {
+ iss.Challenges.DNS = new(DNSChallengeConfig)
+ }
+ iss.Challenges.DNS.Resolvers = d.RemainingArgs()
+ if len(iss.Challenges.DNS.Resolvers) == 0 {
+ return d.ArgErr()
+ }
- case "preferred_chains":
- chainPref, err := ParseCaddyfilePreferredChainsOptions(d)
- if err != nil {
- return err
- }
- iss.PreferredChains = chainPref
+ case "dns_ttl":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ ttlStr := d.Val()
+ ttl, err := caddy.ParseDuration(ttlStr)
+ if err != nil {
+ return d.Errf("invalid dns_ttl duration %s: %v", ttlStr, err)
+ }
+ if iss.Challenges == nil {
+ iss.Challenges = new(ChallengesConfig)
+ }
+ if iss.Challenges.DNS == nil {
+ iss.Challenges.DNS = new(DNSChallengeConfig)
+ }
+ iss.Challenges.DNS.TTL = caddy.Duration(ttl)
- default:
- return d.Errf("unrecognized ACME issuer property: %s", d.Val())
+ case "dns_challenge_override_domain":
+ arg := d.RemainingArgs()
+ if len(arg) != 1 {
+ return d.ArgErr()
}
+ if iss.Challenges == nil {
+ iss.Challenges = new(ChallengesConfig)
+ }
+ if iss.Challenges.DNS == nil {
+ iss.Challenges.DNS = new(DNSChallengeConfig)
+ }
+ iss.Challenges.DNS.OverrideDomain = arg[0]
+
+ case "preferred_chains":
+ chainPref, err := ParseCaddyfilePreferredChainsOptions(d)
+ if err != nil {
+ return err
+ }
+ iss.PreferredChains = chainPref
+
+ default:
+ return d.Errf("unrecognized ACME issuer property: %s", d.Val())
}
}
return nil
diff --git a/modules/caddytls/certmanagers.go b/modules/caddytls/certmanagers.go
index ad26468a9..9bb436a37 100644
--- a/modules/caddytls/certmanagers.go
+++ b/modules/caddytls/certmanagers.go
@@ -72,10 +72,9 @@ func (ts Tailscale) canHazCertificate(ctx context.Context, hello *tls.ClientHell
//
// ... tailscale
func (Tailscale) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume cert manager name
+ if d.NextArg() {
+ return d.ArgErr()
}
return nil
}
@@ -169,17 +168,18 @@ func (hcg HTTPCertGetter) GetCertificate(ctx context.Context, hello *tls.ClientH
//
// ... http <url>
func (hcg *HTTPCertGetter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if !d.NextArg() {
- return d.ArgErr()
- }
- hcg.URL = d.Val()
- if d.NextArg() {
- return d.ArgErr()
- }
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- return d.Err("block not allowed here")
- }
+ d.Next() // consume cert manager name
+
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ hcg.URL = d.Val()
+
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+ if d.NextBlock(0) {
+ return d.Err("block not allowed here")
}
return nil
}
diff --git a/modules/caddytls/internalissuer.go b/modules/caddytls/internalissuer.go
index 1cf2461ab..cdc4f493b 100644
--- a/modules/caddytls/internalissuer.go
+++ b/modules/caddytls/internalissuer.go
@@ -155,31 +155,30 @@ func (iss InternalIssuer) Issue(ctx context.Context, csr *x509.CertificateReques
// sign_with_root
// }
func (iss *InternalIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- for d.NextBlock(0) {
- switch d.Val() {
- case "ca":
- if !d.AllArgs(&iss.CA) {
- return d.ArgErr()
- }
-
- case "lifetime":
- if !d.NextArg() {
- return d.ArgErr()
- }
- dur, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return err
- }
- iss.Lifetime = caddy.Duration(dur)
-
- case "sign_with_root":
- if d.NextArg() {
- return d.ArgErr()
- }
- iss.SignWithRoot = true
+ d.Next() // consume issuer name
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "ca":
+ if !d.AllArgs(&iss.CA) {
+ return d.ArgErr()
+ }
+ case "lifetime":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ dur, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return err
}
+ iss.Lifetime = caddy.Duration(dur)
+
+ case "sign_with_root":
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+ iss.SignWithRoot = true
+
}
}
return nil
diff --git a/modules/caddytls/zerosslissuer.go b/modules/caddytls/zerosslissuer.go
index 697bab07d..1c091a076 100644
--- a/modules/caddytls/zerosslissuer.go
+++ b/modules/caddytls/zerosslissuer.go
@@ -208,21 +208,20 @@ func (iss *ZeroSSLIssuer) Revoke(ctx context.Context, cert certmagic.Certificate
//
// Any of the subdirectives for the ACME issuer can be used in the block.
func (iss *ZeroSSLIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
+ d.Next() // consume issuer name
+ if d.NextArg() {
+ iss.APIKey = d.Val()
if d.NextArg() {
- iss.APIKey = d.Val()
- if d.NextArg() {
- return d.ArgErr()
- }
+ return d.ArgErr()
}
+ }
- if iss.ACMEIssuer == nil {
- iss.ACMEIssuer = new(ACMEIssuer)
- }
- err := iss.ACMEIssuer.UnmarshalCaddyfile(d.NewFromNextSegment())
- if err != nil {
- return err
- }
+ if iss.ACMEIssuer == nil {
+ iss.ACMEIssuer = new(ACMEIssuer)
+ }
+ err := iss.ACMEIssuer.UnmarshalCaddyfile(d.NewFromNextSegment())
+ if err != nil {
+ return err
}
return nil
}
diff --git a/modules/filestorage/filestorage.go b/modules/filestorage/filestorage.go
index 672c66cbe..76aff4e8b 100644
--- a/modules/filestorage/filestorage.go
+++ b/modules/filestorage/filestorage.go
@@ -55,7 +55,7 @@ func (s *FileStorage) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if d.NextArg() {
return d.ArgErr()
}
- for nesting := d.Nesting(); d.NextBlock(nesting); {
+ for d.NextBlock(0) {
switch d.Val() {
case "root":
if !d.NextArg() {
diff --git a/modules/logging/encoders.go b/modules/logging/encoders.go
index a4409e7e4..7399423bf 100644
--- a/modules/logging/encoders.go
+++ b/modules/logging/encoders.go
@@ -65,14 +65,13 @@ func (ce *ConsoleEncoder) Provision(_ caddy.Context) error {
// See the godoc on the LogEncoderConfig type for the syntax of
// subdirectives that are common to most/all encoders.
func (ce *ConsoleEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
- err := ce.LogEncoderConfig.UnmarshalCaddyfile(d)
- if err != nil {
- return err
- }
+ d.Next() // consume encoder name
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+ err := ce.LogEncoderConfig.UnmarshalCaddyfile(d)
+ if err != nil {
+ return err
}
return nil
}
@@ -106,14 +105,13 @@ func (je *JSONEncoder) Provision(_ caddy.Context) error {
// See the godoc on the LogEncoderConfig type for the syntax of
// subdirectives that are common to most/all encoders.
func (je *JSONEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- return d.ArgErr()
- }
- err := je.LogEncoderConfig.UnmarshalCaddyfile(d)
- if err != nil {
- return err
- }
+ d.Next() // consume encoder name
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+ err := je.LogEncoderConfig.UnmarshalCaddyfile(d)
+ if err != nil {
+ return err
}
return nil
}
@@ -149,7 +147,7 @@ type LogEncoderConfig struct {
// level_format <format>
// }
func (lec *LogEncoderConfig) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for nesting := d.Nesting(); d.NextBlock(nesting); {
+ for d.NextBlock(0) {
subdir := d.Val()
switch subdir {
case "time_local":
diff --git a/modules/logging/filewriter.go b/modules/logging/filewriter.go
index 11c051d78..3b1001b7c 100644
--- a/modules/logging/filewriter.go
+++ b/modules/logging/filewriter.go
@@ -154,73 +154,72 @@ func (fw FileWriter) OpenWriter() (io.WriteCloser, error) {
// omitted or set to a zero value, then Caddy's default value for that
// subdirective is used.
func (fw *FileWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if !d.NextArg() {
- return d.ArgErr()
- }
- fw.Filename = d.Val()
- if d.NextArg() {
- return d.ArgErr()
- }
+ d.Next() // consume writer name
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ fw.Filename = d.Val()
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "roll_disabled":
+ var f bool
+ fw.Roll = &f
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+
+ case "roll_size":
+ var sizeStr string
+ if !d.AllArgs(&sizeStr) {
+ return d.ArgErr()
+ }
+ size, err := humanize.ParseBytes(sizeStr)
+ if err != nil {
+ return d.Errf("parsing size: %v", err)
+ }
+ fw.RollSizeMB = int(math.Ceil(float64(size) / humanize.MiByte))
- for d.NextBlock(0) {
- switch d.Val() {
- case "roll_disabled":
- var f bool
- fw.Roll = &f
- if d.NextArg() {
- return d.ArgErr()
- }
-
- case "roll_size":
- var sizeStr string
- if !d.AllArgs(&sizeStr) {
- return d.ArgErr()
- }
- size, err := humanize.ParseBytes(sizeStr)
- if err != nil {
- return d.Errf("parsing size: %v", err)
- }
- fw.RollSizeMB = int(math.Ceil(float64(size) / humanize.MiByte))
-
- case "roll_uncompressed":
- var f bool
- fw.RollCompress = &f
- if d.NextArg() {
- return d.ArgErr()
- }
-
- case "roll_local_time":
- fw.RollLocalTime = true
- if d.NextArg() {
- return d.ArgErr()
- }
-
- case "roll_keep":
- var keepStr string
- if !d.AllArgs(&keepStr) {
- return d.ArgErr()
- }
- keep, err := strconv.Atoi(keepStr)
- if err != nil {
- return d.Errf("parsing roll_keep number: %v", err)
- }
- fw.RollKeep = keep
-
- case "roll_keep_for":
- var keepForStr string
- if !d.AllArgs(&keepForStr) {
- return d.ArgErr()
- }
- keepFor, err := caddy.ParseDuration(keepForStr)
- if err != nil {
- return d.Errf("parsing roll_keep_for duration: %v", err)
- }
- if keepFor < 0 {
- return d.Errf("negative roll_keep_for duration: %v", keepFor)
- }
- fw.RollKeepDays = int(math.Ceil(keepFor.Hours() / 24))
+ case "roll_uncompressed":
+ var f bool
+ fw.RollCompress = &f
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+
+ case "roll_local_time":
+ fw.RollLocalTime = true
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+
+ case "roll_keep":
+ var keepStr string
+ if !d.AllArgs(&keepStr) {
+ return d.ArgErr()
+ }
+ keep, err := strconv.Atoi(keepStr)
+ if err != nil {
+ return d.Errf("parsing roll_keep number: %v", err)
+ }
+ fw.RollKeep = keep
+
+ case "roll_keep_for":
+ var keepForStr string
+ if !d.AllArgs(&keepForStr) {
+ return d.ArgErr()
+ }
+ keepFor, err := caddy.ParseDuration(keepForStr)
+ if err != nil {
+ return d.Errf("parsing roll_keep_for duration: %v", err)
+ }
+ if keepFor < 0 {
+ return d.Errf("negative roll_keep_for duration: %v", keepFor)
}
+ fw.RollKeepDays = int(math.Ceil(keepFor.Hours() / 24))
}
}
return nil
diff --git a/modules/logging/filterencoder.go b/modules/logging/filterencoder.go
index 4d51e645c..735d7d424 100644
--- a/modules/logging/filterencoder.go
+++ b/modules/logging/filterencoder.go
@@ -108,50 +108,49 @@ func (fe *FilterEncoder) Provision(ctx caddy.Context) error {
// }
// }
func (fe *FilterEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- for d.NextBlock(0) {
- switch d.Val() {
- case "wrap":
+ d.Next() // consume encoder name
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "wrap":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ moduleName := d.Val()
+ moduleID := "caddy.logging.encoders." + moduleName
+ unm, err := caddyfile.UnmarshalModule(d, moduleID)
+ if err != nil {
+ return err
+ }
+ enc, ok := unm.(zapcore.Encoder)
+ if !ok {
+ return d.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
+ }
+ fe.WrappedRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, nil)
+
+ case "fields":
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
+ field := d.Val()
if !d.NextArg() {
return d.ArgErr()
}
- moduleName := d.Val()
- moduleID := "caddy.logging.encoders." + moduleName
+ filterName := d.Val()
+ moduleID := "caddy.logging.encoders.filter." + filterName
unm, err := caddyfile.UnmarshalModule(d, moduleID)
if err != nil {
return err
}
- enc, ok := unm.(zapcore.Encoder)
+ filter, ok := unm.(LogFieldFilter)
if !ok {
- return d.Errf("module %s (%T) is not a zapcore.Encoder", moduleID, unm)
+ return d.Errf("module %s (%T) is not a logging.LogFieldFilter", moduleID, unm)
}
- fe.WrappedRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, nil)
-
- case "fields":
- for d.NextBlock(1) {
- field := d.Val()
- if !d.NextArg() {
- return d.ArgErr()
- }
- filterName := d.Val()
- moduleID := "caddy.logging.encoders.filter." + filterName
- unm, err := caddyfile.UnmarshalModule(d, moduleID)
- if err != nil {
- return err
- }
- filter, ok := unm.(LogFieldFilter)
- if !ok {
- return d.Errf("module %s (%T) is not a logging.LogFieldFilter", moduleID, unm)
- }
- if fe.FieldsRaw == nil {
- fe.FieldsRaw = make(map[string]json.RawMessage)
- }
- fe.FieldsRaw[field] = caddyconfig.JSONModuleObject(filter, "filter", filterName, nil)
+ if fe.FieldsRaw == nil {
+ fe.FieldsRaw = make(map[string]json.RawMessage)
}
-
- default:
- return d.Errf("unrecognized subdirective %s", d.Val())
+ fe.FieldsRaw[field] = caddyconfig.JSONModuleObject(filter, "filter", filterName, nil)
}
+
+ default:
+ return d.Errf("unrecognized subdirective %s", d.Val())
}
}
return nil
diff --git a/modules/logging/filters.go b/modules/logging/filters.go
index 233d5d713..f38f8c185 100644
--- a/modules/logging/filters.go
+++ b/modules/logging/filters.go
@@ -128,10 +128,9 @@ func (ReplaceFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (f *ReplaceFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- f.Value = d.Val()
- }
+ d.Next() // consume filter name
+ if d.NextArg() {
+ f.Value = d.Val()
}
return nil
}
@@ -169,32 +168,31 @@ func (IPMaskFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (m *IPMaskFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- for d.NextBlock(0) {
- switch d.Val() {
- case "ipv4":
- if !d.NextArg() {
- return d.ArgErr()
- }
- val, err := strconv.Atoi(d.Val())
- if err != nil {
- return d.Errf("error parsing %s: %v", d.Val(), err)
- }
- m.IPv4MaskRaw = val
-
- case "ipv6":
- if !d.NextArg() {
- return d.ArgErr()
- }
- val, err := strconv.Atoi(d.Val())
- if err != nil {
- return d.Errf("error parsing %s: %v", d.Val(), err)
- }
- m.IPv6MaskRaw = val
-
- default:
- return d.Errf("unrecognized subdirective %s", d.Val())
+ d.Next() // consume filter name
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "ipv4":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ val, err := strconv.Atoi(d.Val())
+ if err != nil {
+ return d.Errf("error parsing %s: %v", d.Val(), err)
+ }
+ m.IPv4MaskRaw = val
+
+ case "ipv6":
+ if !d.NextArg() {
+ return d.ArgErr()
}
+ val, err := strconv.Atoi(d.Val())
+ if err != nil {
+ return d.Errf("error parsing %s: %v", d.Val(), err)
+ }
+ m.IPv6MaskRaw = val
+
+ default:
+ return d.Errf("unrecognized subdirective %s", d.Val())
}
}
return nil
@@ -328,45 +326,44 @@ func (QueryFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (m *QueryFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- for d.NextBlock(0) {
- qfa := queryFilterAction{}
- switch d.Val() {
- case "replace":
- if !d.NextArg() {
- return d.ArgErr()
- }
-
- qfa.Type = replaceAction
- qfa.Parameter = d.Val()
-
- if !d.NextArg() {
- return d.ArgErr()
- }
- qfa.Value = d.Val()
-
- case "hash":
- if !d.NextArg() {
- return d.ArgErr()
- }
-
- qfa.Type = hashAction
- qfa.Parameter = d.Val()
-
- case "delete":
- if !d.NextArg() {
- return d.ArgErr()
- }
-
- qfa.Type = deleteAction
- qfa.Parameter = d.Val()
-
- default:
- return d.Errf("unrecognized subdirective %s", d.Val())
+ d.Next() // consume filter name
+ for d.NextBlock(0) {
+ qfa := queryFilterAction{}
+ switch d.Val() {
+ case "replace":
+ if !d.NextArg() {
+ return d.ArgErr()
}
- m.Actions = append(m.Actions, qfa)
+ qfa.Type = replaceAction
+ qfa.Parameter = d.Val()
+
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ qfa.Value = d.Val()
+
+ case "hash":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+
+ qfa.Type = hashAction
+ qfa.Parameter = d.Val()
+
+ case "delete":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+
+ qfa.Type = deleteAction
+ qfa.Parameter = d.Val()
+
+ default:
+ return d.Errf("unrecognized subdirective %s", d.Val())
}
+
+ m.Actions = append(m.Actions, qfa)
}
return nil
}
@@ -460,45 +457,44 @@ func (CookieFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (m *CookieFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- for d.NextBlock(0) {
- cfa := cookieFilterAction{}
- switch d.Val() {
- case "replace":
- if !d.NextArg() {
- return d.ArgErr()
- }
-
- cfa.Type = replaceAction
- cfa.Name = d.Val()
-
- if !d.NextArg() {
- return d.ArgErr()
- }
- cfa.Value = d.Val()
-
- case "hash":
- if !d.NextArg() {
- return d.ArgErr()
- }
-
- cfa.Type = hashAction
- cfa.Name = d.Val()
-
- case "delete":
- if !d.NextArg() {
- return d.ArgErr()
- }
-
- cfa.Type = deleteAction
- cfa.Name = d.Val()
-
- default:
- return d.Errf("unrecognized subdirective %s", d.Val())
+ d.Next() // consume filter name
+ for d.NextBlock(0) {
+ cfa := cookieFilterAction{}
+ switch d.Val() {
+ case "replace":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+
+ cfa.Type = replaceAction
+ cfa.Name = d.Val()
+
+ if !d.NextArg() {
+ return d.ArgErr()
}
+ cfa.Value = d.Val()
- m.Actions = append(m.Actions, cfa)
+ case "hash":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+
+ cfa.Type = hashAction
+ cfa.Name = d.Val()
+
+ case "delete":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+
+ cfa.Type = deleteAction
+ cfa.Name = d.Val()
+
+ default:
+ return d.Errf("unrecognized subdirective %s", d.Val())
}
+
+ m.Actions = append(m.Actions, cfa)
}
return nil
}
@@ -571,13 +567,12 @@ func (RegexpFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (f *RegexpFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- f.RawRegexp = d.Val()
- }
- if d.NextArg() {
- f.Value = d.Val()
- }
+ d.Next() // consume filter name
+ if d.NextArg() {
+ f.RawRegexp = d.Val()
+ }
+ if d.NextArg() {
+ f.Value = d.Val()
}
return nil
}
@@ -625,10 +620,9 @@ func (RenameFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (f *RenameFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if d.NextArg() {
- f.Name = d.Val()
- }
+ d.Next() // consume filter name
+ if d.NextArg() {
+ f.Name = d.Val()
}
return nil
}
diff --git a/modules/logging/netwriter.go b/modules/logging/netwriter.go
index 1939cb711..dc2b0922c 100644
--- a/modules/logging/netwriter.go
+++ b/modules/logging/netwriter.go
@@ -117,35 +117,34 @@ func (nw NetWriter) OpenWriter() (io.WriteCloser, error) {
// soft_start
// }
func (nw *NetWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- if !d.NextArg() {
- return d.ArgErr()
- }
- nw.Address = d.Val()
- if d.NextArg() {
- return d.ArgErr()
- }
- for nesting := d.Nesting(); d.NextBlock(nesting); {
- switch d.Val() {
- case "dial_timeout":
- if !d.NextArg() {
- return d.ArgErr()
- }
- timeout, err := caddy.ParseDuration(d.Val())
- if err != nil {
- return d.Errf("invalid duration: %s", d.Val())
- }
- if d.NextArg() {
- return d.ArgErr()
- }
- nw.DialTimeout = caddy.Duration(timeout)
-
- case "soft_start":
- if d.NextArg() {
- return d.ArgErr()
- }
- nw.SoftStart = true
+ d.Next() // consume writer name
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ nw.Address = d.Val()
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "dial_timeout":
+ if !d.NextArg() {
+ return d.ArgErr()
+ }
+ timeout, err := caddy.ParseDuration(d.Val())
+ if err != nil {
+ return d.Errf("invalid duration: %s", d.Val())
+ }
+ if d.NextArg() {
+ return d.ArgErr()
+ }
+ nw.DialTimeout = caddy.Duration(timeout)
+
+ case "soft_start":
+ if d.NextArg() {
+ return d.ArgErr()
}
+ nw.SoftStart = true
}
}
return nil
diff --git a/modules/metrics/metrics.go b/modules/metrics/metrics.go
index a9e0f0efa..dc6196a15 100644
--- a/modules/metrics/metrics.go
+++ b/modules/metrics/metrics.go
@@ -78,19 +78,18 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
// disable_openmetrics
// }
func (m *Metrics) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
- for d.Next() {
- args := d.RemainingArgs()
- if len(args) > 0 {
- return d.ArgErr()
- }
+ d.Next() // consume directive name
+ args := d.RemainingArgs()
+ if len(args) > 0 {
+ return d.ArgErr()
+ }
- for d.NextBlock(0) {
- switch d.Val() {
- case "disable_openmetrics":
- m.DisableOpenMetrics = true
- default:
- return d.Errf("unrecognized subdirective %q", d.Val())
- }
+ for d.NextBlock(0) {
+ switch d.Val() {
+ case "disable_openmetrics":
+ m.DisableOpenMetrics = true
+ default:
+ return d.Errf("unrecognized subdirective %q", d.Val())
}
}
return nil