diff options
author | Jack Baron <jackmbaron@gmail.com> | 2020-12-09 18:28:14 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-09 11:28:14 -0700 |
commit | c898a37f4080fe3013974bee9a44ce98bd900cc3 (patch) | |
tree | 14f9bf7d2259f83040031bda93d548badfd54449 | |
parent | 31fbcd74016f35c4edf89b5de9c8a519663d588b (diff) |
httpcaddyfile: support matching headers that do not exist (#3909)
* add integration test for null header matcher
* implement null header matcher syntax
* avoid repeating magic !
* check for field following ! character
-rw-r--r-- | caddytest/integration/caddyfile_adapt/matcher_syntax.txt | 24 | ||||
-rw-r--r-- | modules/caddyhttp/matchers.go | 29 |
2 files changed, 48 insertions, 5 deletions
diff --git a/caddytest/integration/caddyfile_adapt/matcher_syntax.txt b/caddytest/integration/caddyfile_adapt/matcher_syntax.txt index c5c2760..019ce14 100644 --- a/caddytest/integration/caddyfile_adapt/matcher_syntax.txt +++ b/caddytest/integration/caddyfile_adapt/matcher_syntax.txt @@ -31,6 +31,12 @@ query bar=baz } respond @matcher8 "query matcher merging pairs with the same keys" + + @matcher9 { + header !Foo + header Bar foo + } + respond @matcher9 "header matcher with null field matcher" } ---------- { @@ -183,6 +189,24 @@ "handler": "static_response" } ] + }, + { + "match": [ + { + "header": { + "Bar": [ + "foo" + ], + "Foo": null + } + } + ], + "handle": [ + { + "body": "header matcher with null field matcher", + "handler": "static_response" + } + ] } ] } diff --git a/modules/caddyhttp/matchers.go b/modules/caddyhttp/matchers.go index c5cf21d..4886ba6 100644 --- a/modules/caddyhttp/matchers.go +++ b/modules/caddyhttp/matchers.go @@ -470,13 +470,32 @@ func (m *MatchHeader) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { } for d.Next() { var field, val string - if !d.Args(&field, &val) { - return d.Errf("malformed header matcher: expected both field and value") + if !d.Args(&field) { + return d.Errf("malformed header matcher: expected field") } - // If multiple header matchers with the same header field are defined, - // we want to add the existing to the list of headers (will be OR'ed) - http.Header(*m).Add(field, val) + if strings.HasPrefix(field, "!") { + if len(field) == 1 { + return d.Errf("malformed header matcher: must have field name following ! character") + } + + field = field[1:] + headers := *m + headers[field] = nil + m = &headers + if d.NextArg() { + return d.Errf("malformed header matcher: null matching headers cannot have a field value") + } + } else { + if !d.NextArg() { + return d.Errf("malformed header matcher: expected both field and value") + } + + // If multiple header matchers with the same header field are defined, + // we want to add the existing to the list of headers (will be OR'ed) + val = d.Val() + http.Header(*m).Add(field, val) + } if d.NextBlock(0) { return d.Err("malformed header matcher: blocks are not supported") |