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
This commit is contained in:
Jack Baron 2020-12-09 18:28:14 +00:00 committed by GitHub
parent 31fbcd7401
commit c898a37f40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 5 deletions

View file

@ -31,6 +31,12 @@
query bar=baz query bar=baz
} }
respond @matcher8 "query matcher merging pairs with the same keys" 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" "handler": "static_response"
} }
] ]
},
{
"match": [
{
"header": {
"Bar": [
"foo"
],
"Foo": null
}
}
],
"handle": [
{
"body": "header matcher with null field matcher",
"handler": "static_response"
}
]
} }
] ]
} }

View file

@ -470,13 +470,32 @@ func (m *MatchHeader) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
} }
for d.Next() { for d.Next() {
var field, val string var field, val string
if !d.Args(&field, &val) { if !d.Args(&field) {
return d.Errf("malformed header matcher: expected both field and value") return d.Errf("malformed header matcher: expected field")
} }
// If multiple header matchers with the same header field are defined, if strings.HasPrefix(field, "!") {
// we want to add the existing to the list of headers (will be OR'ed) if len(field) == 1 {
http.Header(*m).Add(field, val) 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) { if d.NextBlock(0) {
return d.Err("malformed header matcher: blocks are not supported") return d.Err("malformed header matcher: blocks are not supported")