diff --git a/docs/docs/configuration/alpha_config.md b/docs/docs/configuration/alpha_config.md
index 54ccb01e..9e6c2873 100644
--- a/docs/docs/configuration/alpha_config.md
+++ b/docs/docs/configuration/alpha_config.md
@@ -266,6 +266,7 @@ response header.
| ----- | ---- | ----------- |
| `name` | _string_ | Name is the header name to be used for this set of values.
Names should be unique within a list of Headers. |
| `preserveRequestValue` | _bool_ | PreserveRequestValue determines whether any values for this header
should be preserved for the request to the upstream server.
This option only applies to injected request headers.
Defaults to false (headers that match this header will be stripped). |
+| `InsecureSkipHeaderNormalization` | _bool_ | InsecureSkipHeaderNormalization disables normalizing the header name
According to RFC 7230 Section 3.2 there aren't any rules about
capitalization of header names, but the standard practice is to use
Title-Case (e.g. X-Forwarded-For). By default, header names will be
normalized to Title-Case and any incoming headers that match will be
treated as the same header. Additionally underscores (_) in header names
will be converted to dashes (-) when normalizing.
Defaults to false (header names will be normalized). |
| `values` | _[[]HeaderValue](#headervalue)_ | Values contains the desired values for this header |
### HeaderValue
diff --git a/pkg/apis/options/header.go b/pkg/apis/options/header.go
index 90e6445c..4299fd35 100644
--- a/pkg/apis/options/header.go
+++ b/pkg/apis/options/header.go
@@ -13,6 +13,16 @@ type Header struct {
// Defaults to false (headers that match this header will be stripped).
PreserveRequestValue bool `json:"preserveRequestValue,omitempty"`
+ // InsecureSkipHeaderNormalization disables normalizing the header name
+ // According to RFC 7230 Section 3.2 there aren't any rules about
+ // capitalization of header names, but the standard practice is to use
+ // Title-Case (e.g. X-Forwarded-For). By default, header names will be
+ // normalized to Title-Case and any incoming headers that match will be
+ // treated as the same header. Additionally underscores (_) in header names
+ // will be converted to dashes (-) when normalizing.
+ // Defaults to false (header names will be normalized).
+ InsecureSkipHeaderNormalization bool `json:"InsecureSkipHeaderNormalization,omitempty"`
+
// Values contains the desired values for this header
Values []HeaderValue `json:"values,omitempty"`
}
diff --git a/pkg/middleware/headers.go b/pkg/middleware/headers.go
index f833848f..623d50e9 100644
--- a/pkg/middleware/headers.go
+++ b/pkg/middleware/headers.go
@@ -53,6 +53,11 @@ func flattenHeaders(headers http.Header) {
func stripHeaders(headers []options.Header, next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
for _, header := range headers {
+ if header.InsecureSkipHeaderNormalization {
+ req.Header.Del(header.Name)
+ continue
+ }
+
stripNormalizedHeader(req, header)
}
next.ServeHTTP(rw, req)
diff --git a/pkg/middleware/headers_test.go b/pkg/middleware/headers_test.go
index 14937955..6a60ec01 100644
--- a/pkg/middleware/headers_test.go
+++ b/pkg/middleware/headers_test.go
@@ -205,7 +205,7 @@ var _ = Describe("Headers Suite", func() {
expectedHeaders: nil,
expectedErr: "error building request header injector: error building request injector: error building injector for header \"X-Auth-Request-Authorization\": error loading basicAuthPassword: secret source is invalid: exactly one entry required, specify either value, fromEnv or fromFile",
}),
- Entry("strips normalized variants before injecting (no preservation)", headersTableInput{
+ Entry("strips normalized variants before injecting", headersTableInput{
headers: []options.Header{
{
Name: "X-Auth-Request-User",
@@ -226,6 +226,29 @@ var _ = Describe("Headers Suite", func() {
},
expectedErr: "",
}),
+ Entry("doesn't strip normalized variants before injecting", headersTableInput{
+ headers: []options.Header{
+ {
+ Name: "X-Auth-Request-User",
+ InsecureSkipHeaderNormalization: true,
+ Values: []options.HeaderValue{
+ {
+ ClaimSource: &options.ClaimSource{Claim: "user"},
+ },
+ },
+ },
+ },
+ initialHeaders: http.Header{
+ "X-Auth-Request-User": []string{"old"},
+ "X-Auth_Request_User": []string{"evil"},
+ },
+ session: &sessionsapi.SessionState{User: "user-123"},
+ expectedHeaders: http.Header{
+ "X-Auth-Request-User": []string{"user-123"},
+ "X-Auth_Request_User": []string{"evil"},
+ },
+ expectedErr: "",
+ }),
)
DescribeTable("the response header injector",