caddyfile: Normalize & flatten all unmarshalers (#6037)

This commit is contained in:
Francis Lavoie 2024-01-23 19:36:59 -05:00 committed by GitHub
parent 54823f52bc
commit 750d0b8331
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 3026 additions and 3013 deletions

View File

@ -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)
}

View File

@ -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,7 +109,6 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
var onDemand bool
var reusePrivateKeys bool
for h.Next() {
// file certificate loader
firstLine := h.RemainingArgs()
switch len(firstLine) {
@ -177,7 +175,7 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
}
var hasBlock bool
for nesting := h.Nesting(); h.NextBlock(nesting); {
for h.NextBlock(0) {
hasBlock = true
switch h.Val() {
@ -525,7 +523,6 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
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() {
h.Next() // consume directive name
if !h.NextArg() {
return nil, h.ArgErr()
}
name = h.Val()
if h.NextArg() {
return nil, h.ArgErr()
}
}
return caddyhttp.VarsMiddleware{"fs": name}, nil
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,12 +933,14 @@ 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.
@ -1128,7 +1112,6 @@ func parseLogHelper(h Helper, globalLogNames map[string]struct{}) ([]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() {
h.Next() // consume directive name
if h.NextArg() {
return nil, h.ArgErr()
}
}
return caddyhttp.VarsMiddleware{"skip_log": true}, nil
}

View File

@ -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 {

View File

@ -1381,7 +1381,8 @@ func (st *ServerType) compileEncodedMatcherSets(sblock serverBlock) ([]caddy.Mod
}
func parseMatcherDefinitions(d *caddyfile.Dispenser, matchers map[string]caddy.ModuleMap) error {
for d.Next() {
d.Next() // advance to the first token
// this is the "name" for "named matchers"
definitionName := d.Val()
@ -1417,11 +1418,16 @@ func parseMatcherDefinitions(d *caddyfile.Dispenser, matchers map[string]caddy.M
// and that it's probably an 'expression' matcher
if d.NextArg() {
if d.Token().Quoted() {
err := makeMatcher("expression", []caddyfile.Token{d.Token()})
// 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
}
continue
return nil
}
// if it wasn't quoted, then we need to rewind after calling
@ -1444,7 +1450,6 @@ func parseMatcherDefinitions(d *caddyfile.Dispenser, matchers map[string]caddy.M
return err
}
}
}
return nil
}

View File

@ -62,8 +62,8 @@ 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()
@ -73,13 +73,12 @@ func parseOptHTTPPort(d *caddyfile.Dispenser, _ any) (any, error) {
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()
@ -89,14 +88,12 @@ func parseOptHTTPSPort(d *caddyfile.Dispenser, _ any) (any, error) {
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()
@ -112,6 +109,8 @@ func parseOptOrder(d *caddyfile.Dispenser, _ any) (any, error) {
}
pos := d.Val()
newOrder := directiveOrder
// if directive exists, first remove it
for i, d := range newOrder {
if d == dirName {
@ -162,7 +161,6 @@ func parseOptOrder(d *caddyfile.Dispenser, _ any) (any, error) {
break
}
}
}
directiveOrder = newOrder
@ -223,11 +221,11 @@ func parseOptACMEDNS(d *caddyfile.Dispenser, _ any) (any, error) {
func parseOptACMEEAB(d *caddyfile.Dispenser, _ any) (any, error) {
eab := new(acme.EAB)
for d.Next() {
d.Next() // consume option name
if d.NextArg() {
return nil, d.ArgErr()
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
for d.NextBlock(0) {
switch d.Val() {
case "key_id":
if !d.NextArg() {
@ -245,17 +243,19 @@ func parseOptACMEEAB(d *caddyfile.Dispenser, _ any) (any, error) {
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
// get issuer module name
if !d.Next() {
return nil, d.ArgErr()
}
modID := "tls.issuance." + d.Val()
@ -268,12 +268,11 @@ func parseOptCertIssuer(d *caddyfile.Dispenser, existing any) (any, error) {
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,8 +293,9 @@ 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" {
@ -310,7 +310,7 @@ func parseOptAdmin(d *caddyfile.Dispenser, _ any) (any, error) {
}
}
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
for d.NextBlock(0) {
switch d.Val() {
case "enforce_origin":
adminCfg.EnforceOrigin = true
@ -322,7 +322,6 @@ func parseOptAdmin(d *caddyfile.Dispenser, _ any) (any, error) {
return nil, d.Errf("unrecognized parameter '%s'", d.Val())
}
}
}
if adminCfg.Listen == "" && !adminCfg.Disabled {
adminCfg.Listen = caddy.DefaultAdminListen
}
@ -330,12 +329,13 @@ func parseOptAdmin(d *caddyfile.Dispenser, _ any) (any, error) {
}
func parseOptOnDemand(d *caddyfile.Dispenser, _ any) (any, error) {
var ond *caddytls.OnDemandConfig
for d.Next() {
d.Next() // consume option name
if d.NextArg() {
return nil, d.ArgErr()
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
var ond *caddytls.OnDemandConfig
for d.NextBlock(0) {
switch d.Val() {
case "ask":
if !d.NextArg() {
@ -382,7 +382,6 @@ func parseOptOnDemand(d *caddyfile.Dispenser, _ any) (any, error) {
return nil, d.Errf("unrecognized parameter '%s'", d.Val())
}
}
}
if ond == nil {
return nil, d.Err("expected at least one config parameter for on_demand_tls")
}
@ -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()
}

View File

@ -48,10 +48,12 @@ 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); {
pki := &caddypki.PKI{
CAs: make(map[string]*caddypki.CA),
}
for d.NextBlock(0) {
switch d.Val() {
case "ca":
pkiCa := new(caddypki.CA)
@ -164,8 +166,6 @@ func parsePKIApp(d *caddyfile.Dispenser, existingVal any) (any, error) {
return nil, d.Errf("unrecognized pki option '%s'", d.Val())
}
}
}
return pki, nil
}

View File

@ -53,15 +53,16 @@ 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() {
return nil, d.ArgErr()
}
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
for d.NextBlock(0) {
switch d.Val() {
case "name":
if serverOpts.ListenerAddress == "" {
@ -283,7 +284,6 @@ func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
return nil, d.Errf("unrecognized servers option '%s'", d.Val())
}
}
}
return serverOpts, nil
}

View File

@ -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"
]
}
}
}
]
}
]
}
}
}
}
}

View File

@ -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":

View File

@ -34,10 +34,11 @@ 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()
@ -84,7 +85,6 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
Salt: b64Salt,
})
}
}
return Authentication{
ProvidersRaw: caddy.ModuleMap{

View File

@ -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() {
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(), " ")
} else {
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
}

View File

@ -54,11 +54,9 @@ 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)
for d.Next() {
prefer := []string{}
for _, arg := range d.RemainingArgs() {
mod, err := caddy.GetModule("http.encoders." + arg)
if err != nil {
@ -75,6 +73,7 @@ func (enc *Encode) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
prefer = append(prefer, arg)
}
responseMatchers := make(map[string]caddyhttp.ResponseMatcher)
for d.NextBlock(0) {
switch d.Val() {
case "minimum_length":
@ -111,7 +110,6 @@ func (enc *Encode) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
prefer = append(prefer, name)
}
}
}
// use the order in which the encoders were defined.
enc.Prefer = prefer

View File

@ -44,9 +44,9 @@ func (Gzip) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the handler from Caddyfile tokens.
func (g *Gzip) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume option name
if !d.NextArg() {
continue
return nil
}
levelStr := d.Val()
level, err := strconv.Atoi(levelStr)
@ -54,7 +54,6 @@ func (g *Gzip) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return err
}
g.Level = level
}
return nil
}

View File

@ -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 != "" {

View File

@ -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) {

View File

@ -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,7 +63,6 @@ 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
if h.NextArg() {
@ -133,7 +130,6 @@ func parseCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
return nil, h.Err(err.Error())
}
}
}
var configValues []httpcaddyfile.ConfigValue
if !reflect.DeepEqual(handler, makeHandler()) {
@ -151,18 +147,15 @@ 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()
}
@ -200,7 +193,6 @@ func parseReqHdrCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue,
if h.NextArg() {
return nil, h.ArgErr()
}
}
return configValues, nil
}

View File

@ -79,7 +79,7 @@ func (MatchRemoteIP) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume matcher name
for d.NextArg() {
if d.Val() == "forwarded" {
if len(m.Ranges) > 0 {
@ -97,7 +97,6 @@ func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if d.NextBlock(0) {
return d.Err("malformed remote_ip matcher: blocks are not supported")
}
}
return nil
}
@ -189,7 +188,7 @@ func (MatchClientIP) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (m *MatchClientIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume matcher name
for d.NextArg() {
if d.Val() == "private_ranges" {
m.Ranges = append(m.Ranges, PrivateRangesCIDR()...)
@ -200,7 +199,6 @@ func (m *MatchClientIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if d.NextBlock(0) {
return d.Err("malformed client_ip matcher: blocks are not supported")
}
}
return nil
}

View File

@ -42,9 +42,10 @@ 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()
@ -109,7 +110,5 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
handler.Mappings = append(handler.Mappings, mapping)
}
}
return handler, nil
}

View File

@ -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

View File

@ -39,7 +39,8 @@ func (ListenerWrapper) CaddyModule() caddy.ModuleInfo {
// fallback_policy <policy>
// }
func (w *ListenerWrapper) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume wrapper name
// No same-line options are supported
if d.NextArg() {
return d.ArgErr()
@ -74,7 +75,6 @@ func (w *ListenerWrapper) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.ArgErr()
}
}
}
return nil
}

View File

@ -44,21 +44,23 @@ func init() {
// Placeholders are accepted in resource and header field
// name and value and replacement tokens.
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
h.Next() // consume directive name
handler := new(Handler)
for h.Next() {
// inline resources
if h.NextArg() {
handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
}
// optional block
for outerNesting := h.Nesting(); h.NextBlock(outerNesting); {
for h.NextBlock(0) {
switch h.Val() {
case "headers":
if h.NextArg() {
return nil, h.ArgErr()
}
for innerNesting := h.Nesting(); h.NextBlock(innerNesting); {
for nesting := h.Nesting(); h.NextBlock(nesting); {
var err error
// include current token, which we treat as an argument here
@ -100,7 +102,5 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
handler.Resources = append(handler.Resources, Resource{Target: h.Val()})
}
}
}
return handler, nil
}

View File

@ -26,9 +26,10 @@ 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() {
@ -42,11 +43,11 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
return nil, h.Errf("parsing max_size: %v", err)
}
rb.MaxSize = int64(size)
default:
return nil, h.Errf("unrecognized servers option '%s'", h.Val())
}
}
}
return rb, nil
}

View File

@ -67,7 +67,7 @@ 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() {
d.Next() // consume matcher name
definitionName := d.Val()
if _, ok := matchers[definitionName]; ok {
@ -114,8 +114,6 @@ func ParseNamedResponseMatcher(d *caddyfile.Dispenser, matchers map[string]Respo
return d.Errf("unrecognized response matcher %s", d.Val())
}
}
matchers[definitionName] = matcher
}
return nil
}

View File

@ -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,7 +930,7 @@ 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() {
d.Next() // consume transport name
for d.NextBlock(0) {
switch d.Val() {
case "read_buffer":
@ -1222,7 +1222,6 @@ func (h *HTTPTransport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized subdirective %s", d.Val())
}
}
}
return nil
}
@ -1241,12 +1240,13 @@ func parseCopyResponseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHan
// status <status>
// }
func (h *CopyResponseHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
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])
break
return nil
}
}
@ -1261,7 +1261,6 @@ func (h *CopyResponseHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized subdirective '%s'", d.Val())
}
}
}
return nil
}
@ -1281,7 +1280,8 @@ func parseCopyResponseHeadersCaddyfile(h httpcaddyfile.Helper) (caddyhttp.Middle
// exclude <fields...>
// }
func (h *CopyResponseHeadersHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume directive name
args := d.RemainingArgs()
if len(args) > 0 {
return d.ArgErr()
@ -1299,7 +1299,6 @@ func (h *CopyResponseHeadersHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser)
return d.Errf("unrecognized subdirective '%s'", d.Val())
}
}
}
return nil
}
@ -1315,7 +1314,8 @@ func (h *CopyResponseHeadersHandler) UnmarshalCaddyfile(d *caddyfile.Dispenser)
// dial_fallback_delay <timeout>
// }
func (u *SRVUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume upstream source name
args := d.RemainingArgs()
if len(args) > 1 {
return d.ArgErr()
@ -1396,8 +1396,6 @@ func (u *SRVUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized srv option '%s'", d.Val())
}
}
}
return nil
}
@ -1413,7 +1411,8 @@ func (u *SRVUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
// versions ipv4|ipv6
// }
func (u *AUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume upstream source name
args := d.RemainingArgs()
if len(args) > 2 {
return d.ArgErr()
@ -1510,8 +1509,6 @@ func (u *AUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized a option '%s'", d.Val())
}
}
}
return nil
}
@ -1521,12 +1518,13 @@ func (u *AUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
// <source> [...]
// }
func (u *MultiUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume upstream source name
if d.NextArg() {
return d.ArgErr()
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
for d.NextBlock(0) {
dynModule := d.Val()
modID := "http.reverse_proxy.upstreams." + dynModule
unm, err := caddyfile.UnmarshalModule(d, modID)
@ -1539,8 +1537,6 @@ func (u *MultiUpstreams) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
}
u.SourcesRaw = append(u.SourcesRaw, caddyconfig.JSONModuleObject(source, "source", dynModule, nil))
}
}
return nil
}

View File

@ -46,7 +46,7 @@ func init() {
// capture_stderr
// }
func (t *Transport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume transport name
for d.NextBlock(0) {
switch d.Val() {
case "root":
@ -117,7 +117,6 @@ func (t *Transport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized subdirective %s", d.Val())
}
}
}
return nil
}

View File

@ -68,11 +68,10 @@ 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() {
d.Next() // consume policy name
if d.NextArg() {
return d.ArgErr()
}
}
return nil
}
@ -98,7 +97,8 @@ func (WeightedRoundRobinSelection) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *WeightedRoundRobinSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume policy name
args := d.RemainingArgs()
if len(args) == 0 {
return d.ArgErr()
@ -114,7 +114,6 @@ func (r *WeightedRoundRobinSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser)
}
r.Weights = append(r.Weights, weightInt)
}
}
return nil
}
@ -179,7 +178,8 @@ func (RandomChoiceSelection) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (r *RandomChoiceSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume policy name
if !d.NextArg() {
return d.ArgErr()
}
@ -189,7 +189,6 @@ func (r *RandomChoiceSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error
return d.Errf("invalid choice value '%s': %v", chooseStr, err)
}
r.Choose = choose
}
return nil
}
@ -280,11 +279,10 @@ 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() {
d.Next() // consume policy name
if d.NextArg() {
return d.ArgErr()
}
}
return nil
}
@ -320,11 +318,10 @@ 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() {
d.Next() // consume policy name
if d.NextArg() {
return d.ArgErr()
}
}
return nil
}
@ -352,11 +349,10 @@ 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() {
d.Next() // consume policy name
if d.NextArg() {
return d.ArgErr()
}
}
return nil
}
@ -383,11 +379,10 @@ 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() {
d.Next() // consume policy name
if d.NextArg() {
return d.ArgErr()
}
}
return nil
}
@ -416,11 +411,10 @@ 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() {
d.Next() // consume policy name
if d.NextArg() {
return d.ArgErr()
}
}
return nil
}
@ -443,11 +437,10 @@ 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() {
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() {
d.Next() // consume policy name
if !d.NextArg() {
return d.ArgErr()
}
s.Key = d.Val()
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
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() {
d.Next() // consume policy name
if !d.NextArg() {
return d.ArgErr()
}
s.Field = d.Val()
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
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() {

View File

@ -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() {
h.Next() // consume directive name
if !h.NextArg() {
return nil, h.ArgErr()
}
rewr.Method = h.Val()
if h.NextArg() {
return nil, h.ArgErr()
}
}
return rewr, nil
return Rewrite{Method: h.Val()}, nil
}
// parseCaddyfileURI sets up a handler for manipulating (but not "rewriting") the
@ -118,12 +95,15 @@ 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) {
var rewr Rewrite
for h.Next() {
h.Next() // consume directive name
args := h.RemainingArgs()
if len(args) < 2 {
return nil, h.ArgErr()
}
var rewr Rewrite
switch args[0] {
case "strip_prefix":
if len(args) > 2 {
@ -133,11 +113,13 @@ func parseCaddyfileURI(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, err
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) {
@ -165,6 +147,7 @@ func parseCaddyfileURI(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, err
Replace: replace,
Limit: limInt,
})
case "path_regexp":
if len(args) != 3 {
return nil, h.ArgErr()
@ -174,10 +157,10 @@ func parseCaddyfileURI(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, err
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()
}

View File

@ -60,7 +60,7 @@ 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() {
d.Next() // consume directive name
args := d.RemainingArgs()
switch len(args) {
case 1:
@ -91,7 +91,6 @@ func (e *StaticError) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized subdirective '%s'", d.Val())
}
}
}
return nil
}

View File

@ -138,7 +138,7 @@ 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() {
d.Next() // consume directive name
args := d.RemainingArgs()
switch len(args) {
case 1:
@ -174,7 +174,6 @@ func (s *StaticResponse) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized subdirective '%s'", d.Val())
}
}
}
return nil
}

View File

@ -34,8 +34,8 @@ 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":
@ -77,6 +77,5 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
}
}
}
}
return t, nil
}

View File

@ -88,9 +88,8 @@ func (ot *Tracing) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
"span": &ot.SpanName,
}
for d.Next() {
args := d.RemainingArgs()
if len(args) > 0 {
d.Next() // consume directive name
if d.NextArg() {
return d.ArgErr()
}
@ -103,7 +102,6 @@ func (ot *Tracing) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.ArgErr()
}
}
}
return nil
}

View File

@ -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,16 +96,14 @@ func (m *VarsMiddleware) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return nil
}
for d.Next() {
if err := nextVar(true); err != nil {
return err
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
for d.NextBlock(0) {
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) {

View File

@ -34,22 +34,21 @@ 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":
@ -60,6 +59,7 @@ func parseACMEServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
ca = new(caddypki.CA)
}
ca.ID = acmeServer.CA
case "lifetime":
if !h.NextArg() {
return nil, h.ArgErr()
@ -83,7 +83,6 @@ func parseACMEServer(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error
}
}
}
}
configVals := h.NewRoute(matcherSet, acmeServer)

View File

@ -277,14 +277,16 @@ 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() {
return d.ArgErr()
}
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
for d.NextBlock(0) {
switch d.Val() {
case "dir":
if iss.CA != "" {
@ -490,7 +492,6 @@ func (iss *ACMEIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized ACME issuer property: %s", d.Val())
}
}
}
return nil
}

View File

@ -72,11 +72,10 @@ func (ts Tailscale) canHazCertificate(ctx context.Context, hello *tls.ClientHell
//
// ... tailscale
func (Tailscale) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume cert manager name
if d.NextArg() {
return d.ArgErr()
}
}
return nil
}
@ -169,18 +168,19 @@ func (hcg HTTPCertGetter) GetCertificate(ctx context.Context, hello *tls.ClientH
//
// ... http <url>
func (hcg *HTTPCertGetter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume cert manager name
if !d.NextArg() {
return d.ArgErr()
}
hcg.URL = d.Val()
if d.NextArg() {
return d.ArgErr()
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
if d.NextBlock(0) {
return d.Err("block not allowed here")
}
}
return nil
}

View File

@ -155,7 +155,7 @@ func (iss InternalIssuer) Issue(ctx context.Context, csr *x509.CertificateReques
// sign_with_root
// }
func (iss *InternalIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume issuer name
for d.NextBlock(0) {
switch d.Val() {
case "ca":
@ -181,7 +181,6 @@ func (iss *InternalIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
}
}
}
return nil
}

View File

@ -208,7 +208,7 @@ 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() {
@ -223,7 +223,6 @@ func (iss *ZeroSSLIssuer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if err != nil {
return err
}
}
return nil
}

View File

@ -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() {

View File

@ -65,7 +65,7 @@ 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() {
d.Next() // consume encoder name
if d.NextArg() {
return d.ArgErr()
}
@ -73,7 +73,6 @@ func (ce *ConsoleEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
if err != nil {
return err
}
}
return nil
}
@ -106,7 +105,7 @@ 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() {
d.Next() // consume encoder name
if d.NextArg() {
return d.ArgErr()
}
@ -114,7 +113,6 @@ func (je *JSONEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
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":

View File

@ -154,7 +154,7 @@ 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() {
d.Next() // consume writer name
if !d.NextArg() {
return d.ArgErr()
}
@ -222,7 +222,6 @@ func (fw *FileWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
fw.RollKeepDays = int(math.Ceil(keepFor.Hours() / 24))
}
}
}
return nil
}

View File

@ -108,7 +108,7 @@ func (fe *FilterEncoder) Provision(ctx caddy.Context) error {
// }
// }
func (fe *FilterEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume encoder name
for d.NextBlock(0) {
switch d.Val() {
case "wrap":
@ -128,7 +128,7 @@ func (fe *FilterEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
fe.WrappedRaw = caddyconfig.JSONModuleObject(enc, "format", moduleName, nil)
case "fields":
for d.NextBlock(1) {
for nesting := d.Nesting(); d.NextBlock(nesting); {
field := d.Val()
if !d.NextArg() {
return d.ArgErr()
@ -153,7 +153,6 @@ func (fe *FilterEncoder) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized subdirective %s", d.Val())
}
}
}
return nil
}

View File

@ -128,11 +128,10 @@ func (ReplaceFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (f *ReplaceFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume filter name
if d.NextArg() {
f.Value = d.Val()
}
}
return nil
}
@ -169,7 +168,7 @@ func (IPMaskFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (m *IPMaskFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume filter name
for d.NextBlock(0) {
switch d.Val() {
case "ipv4":
@ -196,7 +195,6 @@ func (m *IPMaskFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized subdirective %s", d.Val())
}
}
}
return nil
}
@ -328,7 +326,7 @@ func (QueryFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (m *QueryFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume filter name
for d.NextBlock(0) {
qfa := queryFilterAction{}
switch d.Val() {
@ -367,7 +365,6 @@ func (m *QueryFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
m.Actions = append(m.Actions, qfa)
}
}
return nil
}
@ -460,7 +457,7 @@ func (CookieFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (m *CookieFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume filter name
for d.NextBlock(0) {
cfa := cookieFilterAction{}
switch d.Val() {
@ -499,7 +496,6 @@ func (m *CookieFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
m.Actions = append(m.Actions, cfa)
}
}
return nil
}
@ -571,14 +567,13 @@ func (RegexpFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (f *RegexpFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume filter name
if d.NextArg() {
f.RawRegexp = d.Val()
}
if d.NextArg() {
f.Value = d.Val()
}
}
return nil
}
@ -625,11 +620,10 @@ func (RenameFilter) CaddyModule() caddy.ModuleInfo {
// UnmarshalCaddyfile sets up the module from Caddyfile tokens.
func (f *RenameFilter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume filter name
if d.NextArg() {
f.Name = d.Val()
}
}
return nil
}

View File

@ -117,7 +117,7 @@ func (nw NetWriter) OpenWriter() (io.WriteCloser, error) {
// soft_start
// }
func (nw *NetWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume writer name
if !d.NextArg() {
return d.ArgErr()
}
@ -125,7 +125,7 @@ func (nw *NetWriter) 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 "dial_timeout":
if !d.NextArg() {
@ -147,7 +147,6 @@ func (nw *NetWriter) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
nw.SoftStart = true
}
}
}
return nil
}

View File

@ -78,7 +78,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
// disable_openmetrics
// }
func (m *Metrics) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
d.Next() // consume directive name
args := d.RemainingArgs()
if len(args) > 0 {
return d.ArgErr()
@ -92,7 +92,6 @@ func (m *Metrics) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return d.Errf("unrecognized subdirective %q", d.Val())
}
}
}
return nil
}