@marcel91200 / caddy Mirror · read-only / commits / c898a37f
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

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

Jack Baron committed Dec 9, 2020 at 18:28 UTC c898a37f4080fe3013974bee9a44ce98bd900cc3
2 files changed +48 -5
caddytest/integration/caddyfile_adapt/matcher_syntax.txt
+24
@@ -31,6 +31,12 @@
31 query bar=baz
32 }
33 respond @matcher8 "query matcher merging pairs with the same keys"
34 +
35 + @matcher9 {
36 + header !Foo
37 + header Bar foo
38 + }
39 + respond @matcher9 "header matcher with null field matcher"
40 }
41 ----------
42 {
@@ -183,6 +189,24 @@
189 "handler": "static_response"
190 }
191 ]
192 + },
193 + {
194 + "match": [
195 + {
196 + "header": {
197 + "Bar": [
198 + "foo"
199 + ],
200 + "Foo": null
201 + }
202 + }
203 + ],
204 + "handle": [
205 + {
206 + "body": "header matcher with null field matcher",
207 + "handler": "static_response"
208 + }
209 + ]
210 }
211 ]
212 }
modules/caddyhttp/matchers.go
+24 -5
@@ -470,13 +470,32 @@ func (m *MatchHeader) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
470 }
471 for d.Next() {
472 var field, val string
473 - if !d.Args(&field, &val) {
474 - return d.Errf("malformed header matcher: expected both field and value")
473 + if !d.Args(&field) {
474 + return d.Errf("malformed header matcher: expected field")
475 }
476
477 - // If multiple header matchers with the same header field are defined,
478 - // we want to add the existing to the list of headers (will be OR'ed)
479 - http.Header(*m).Add(field, val)
477 + if strings.HasPrefix(field, "!") {
478 + if len(field) == 1 {
479 + return d.Errf("malformed header matcher: must have field name following ! character")
480 + }
481 +
482 + field = field[1:]
483 + headers := *m
484 + headers[field] = nil
485 + m = &headers
486 + if d.NextArg() {
487 + return d.Errf("malformed header matcher: null matching headers cannot have a field value")
488 + }
489 + } else {
490 + if !d.NextArg() {
491 + return d.Errf("malformed header matcher: expected both field and value")
492 + }
493 +
494 + // If multiple header matchers with the same header field are defined,
495 + // we want to add the existing to the list of headers (will be OR'ed)
496 + val = d.Val()
497 + http.Header(*m).Add(field, val)
498 + }
499
500 if d.NextBlock(0) {
501 return d.Err("malformed header matcher: blocks are not supported")