From 2dd79c58ed9f741cdd4fdd2a12de82a929aa94ff Mon Sep 17 00:00:00 2001 From: Jacob Moore Date: Thu, 11 Jul 2024 18:01:20 -0400 Subject: [PATCH 1/2] OPENAPI: the rewrite header key formatting is odd; let's just make sure all our bases are covered --- config/paths.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/config/paths.go b/config/paths.go index cd1c89f..1265169 100644 --- a/config/paths.go +++ b/config/paths.go @@ -12,9 +12,17 @@ import ( ) const ( - RewriteIdHeader = "RewriteId" + PascalCaseRewriteIdHeader = "Rewriteid" + SnakeCaseRewriteIdHeader = "rewrite_id" + KebabCaseRewriteIdHeader = "Rewrite-Id" ) +var rewriteIdHeaders = []string{ + PascalCaseRewriteIdHeader, + SnakeCaseRewriteIdHeader, + KebabCaseRewriteIdHeader, +} + type PathRewrite struct { RewrittenPath string PathConfiguration *shared.WiretapPathConfig @@ -94,13 +102,49 @@ func rewriteTaget(path string, pathConfig *shared.WiretapPathConfig, configurati } } +func getRewriteIdHeaderValues(req *http.Request) ([]string, bool) { + + // Let's first try to get the header with expected key names + for _, possibleHeaderKey := range rewriteIdHeaders { + + if rewriteIdHeaderValues, ok := req.Header[possibleHeaderKey]; ok { + return rewriteIdHeaderValues, true + } + + if rewriteIdHeaderValues, ok := req.Header[strings.ToLower(possibleHeaderKey)]; ok { + return rewriteIdHeaderValues, true + } + + } + + // Let's now try to ignore case ; this may produce collisions if a user has two headers with similar keys, + // but different capitalization. This is okay, as this is a last ditch effort to find any possible match + var loweredHeaders = make(http.Header) + + for headerKey, headerValues := range req.Header { + for _, headerValue := range headerValues { + loweredHeaders.Set(strings.ToLower(headerKey), headerValue) + } + } + + for _, possibleHeaderKey := range rewriteIdHeaders { + + if rewriteIdHeaderValues, ok := loweredHeaders[strings.ToLower(possibleHeaderKey)]; ok { + return rewriteIdHeaderValues, true + } + + } + + return nil, false +} + func FindPathWithRewriteId(paths []*shared.WiretapPathConfig, req *http.Request) *shared.WiretapPathConfig { if req == nil { return nil } - if rewriteIdHeaderValues, ok := req.Header[RewriteIdHeader]; ok { + if rewriteIdHeaderValues, ok := getRewriteIdHeaderValues(req); ok { for _, pathRewriteConfig := range paths { // Iterate through header values - since it's a multi-value field From 99b7498af36cba539ffb04893b0bd1cfafd56158 Mon Sep 17 00:00:00 2001 From: Jacob Moore Date: Thu, 11 Jul 2024 18:24:10 -0400 Subject: [PATCH 2/2] OPENAPI: added tests --- config/paths.go | 15 ++++--- config/paths_test.go | 93 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 5 deletions(-) diff --git a/config/paths.go b/config/paths.go index 1265169..e57ed0d 100644 --- a/config/paths.go +++ b/config/paths.go @@ -13,7 +13,7 @@ import ( const ( PascalCaseRewriteIdHeader = "Rewriteid" - SnakeCaseRewriteIdHeader = "rewrite_id" + SnakeCaseRewriteIdHeader = "Rewrite_id" KebabCaseRewriteIdHeader = "Rewrite-Id" ) @@ -119,12 +119,17 @@ func getRewriteIdHeaderValues(req *http.Request) ([]string, bool) { // Let's now try to ignore case ; this may produce collisions if a user has two headers with similar keys, // but different capitalization. This is okay, as this is a last ditch effort to find any possible match - var loweredHeaders = make(http.Header) + loweredHeaders := map[string][]string{} for headerKey, headerValues := range req.Header { - for _, headerValue := range headerValues { - loweredHeaders.Set(strings.ToLower(headerKey), headerValue) + loweredKey := strings.ToLower(headerKey) + + if _, ok := loweredHeaders[loweredKey]; ok { + loweredHeaders[loweredKey] = append(loweredHeaders[loweredKey], headerValues...) + } else { + loweredHeaders[loweredKey] = headerValues } + } for _, possibleHeaderKey := range rewriteIdHeaders { @@ -135,7 +140,7 @@ func getRewriteIdHeaderValues(req *http.Request) ([]string, bool) { } - return nil, false + return []string{}, false } func FindPathWithRewriteId(paths []*shared.WiretapPathConfig, req *http.Request) *shared.WiretapPathConfig { diff --git a/config/paths_test.go b/config/paths_test.go index c52a377..8efbccc 100644 --- a/config/paths_test.go +++ b/config/paths_test.go @@ -494,3 +494,96 @@ func TestValidationAllowList_NoPathsRegistered(t *testing.T) { assert.False(t, ignore) } + +func TestGetRewriteHeaderValues(t *testing.T) { + + expectedValue := []string{"ExpectedValue"} + + requestList := []*http.Request{ + { + Header: http.Header{ + "Rewriteid": expectedValue, + "Other-Header": []string{"another header"}, + "other-header": []string{"another another header"}, + }, + }, + { + Header: http.Header{ + "Rewrite-Id": expectedValue, + "Other-Header": []string{"another header"}, + "other-header": []string{"another another header"}, + }, + }, + { + Header: http.Header{ + "Rewrite_id": expectedValue, + "Other-Header": []string{"another header"}, + "other-header": []string{"another another header"}, + }, + }, + { + Header: http.Header{ + "RewriteId": expectedValue, + "Other-Header": []string{"another header"}, + "other-header": []string{"another another header"}, + }, + }, + { + Header: http.Header{ + "RewrIte-Id": expectedValue, + "Other-Header": []string{"another header"}, + "other-header": []string{"another another header"}, + }, + }, + { + Header: http.Header{ + "rewriteid": expectedValue, + "Other-Header": []string{"another header"}, + "other-header": []string{"another another header"}, + }, + }, + { + Header: http.Header{ + "rewrite-id": expectedValue, + "Other-Header": []string{"another header"}, + "other-header": []string{"another another header"}, + }, + }, + { + Header: http.Header{ + "rewrite_id": expectedValue, + "Other-Header": []string{"another header"}, + "other-header": []string{"another another header"}, + }, + }, + } + + for _, request := range requestList { + actualValue, found := getRewriteIdHeaderValues(request) + assert.Equal(t, expectedValue, actualValue) + assert.True(t, found) + } + +} + +func TestGetRewriteHeaderValues_MissingHeader(t *testing.T) { + + requestList := []*http.Request{ + { + Header: http.Header{ + "Other-Header": []string{"another header"}, + "other-header": []string{"another another header"}, + }, + }, + { + Header: http.Header{}, + }, + } + + for _, request := range requestList { + actualValue, found := getRewriteIdHeaderValues(request) + assert.Equal(t, []string{}, actualValue) + assert.False(t, found) + } + +}