From 0bcd02d5f669869b0c79c00ea3c5a3f6a7072b20 Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Wed, 15 Jun 2022 09:57:43 -0600 Subject: [PATCH] headers: Support wildcards for delete ops (close #4830) (#4831) --- modules/caddyhttp/headers/headers.go | 34 +++++++++++++++++++++-- modules/caddyhttp/headers/headers_test.go | 20 +++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/modules/caddyhttp/headers/headers.go b/modules/caddyhttp/headers/headers.go index 4cef0a9fbe9..f67df92820f 100644 --- a/modules/caddyhttp/headers/headers.go +++ b/modules/caddyhttp/headers/headers.go @@ -118,10 +118,16 @@ type HeaderOps struct { // Sets HTTP headers; replaces existing header fields. Set http.Header `json:"set,omitempty"` - // Names of HTTP header fields to delete. + // Names of HTTP header fields to delete. Basic wildcards are supported: + // + // - Start with `*` for all field names with the given suffix; + // - End with `*` for all field names with the given prefix; + // - Start and end with `*` for all field names containing a substring. Delete []string `json:"delete,omitempty"` - // Performs substring replacements of HTTP headers in-situ. + // Performs in-situ substring replacements of HTTP headers. + // Keys are the field names on which to perform the associated replacements. + // If the field name is `*`, the replacements are performed on all header fields. Replace map[string][]Replacement `json:"replace,omitempty"` } @@ -208,7 +214,29 @@ func (ops HeaderOps) ApplyTo(hdr http.Header, repl *caddy.Replacer) { // delete for _, fieldName := range ops.Delete { - hdr.Del(repl.ReplaceAll(fieldName, "")) + fieldName = strings.ToLower(repl.ReplaceAll(fieldName, "")) + switch { + case strings.HasPrefix(fieldName, "*") && strings.HasSuffix(fieldName, "*"): + for existingField := range hdr { + if strings.Contains(strings.ToLower(existingField), fieldName[1:len(fieldName)-1]) { + delete(hdr, existingField) + } + } + case strings.HasPrefix(fieldName, "*"): + for existingField := range hdr { + if strings.HasSuffix(strings.ToLower(existingField), fieldName[1:]) { + delete(hdr, existingField) + } + } + case strings.HasSuffix(fieldName, "*"): + for existingField := range hdr { + if strings.HasPrefix(strings.ToLower(existingField), fieldName[:len(fieldName)-1]) { + delete(hdr, existingField) + } + } + default: + hdr.Del(fieldName) + } } // replace diff --git a/modules/caddyhttp/headers/headers_test.go b/modules/caddyhttp/headers/headers_test.go index fb68225e37e..d74e6fc3a07 100644 --- a/modules/caddyhttp/headers/headers_test.go +++ b/modules/caddyhttp/headers/headers_test.go @@ -79,6 +79,26 @@ func TestHandler(t *testing.T) { "Keep-Me": []string{"i swear i'm innocent"}, }, }, + { + handler: Handler{ + Request: &HeaderOps{ + Delete: []string{ + "*-suffix", + "prefix-*", + "*_*", + }, + }, + }, + reqHeader: http.Header{ + "Header-Suffix": []string{"lalala"}, + "Prefix-Test": []string{"asdf"}, + "Host_Header": []string{"silly django... sigh"}, // see issue #4830 + "Keep-Me": []string{"foofoofoo"}, + }, + expectedReqHeader: http.Header{ + "Keep-Me": []string{"foofoofoo"}, + }, + }, { handler: Handler{ Request: &HeaderOps{