Allow to use regular expressions for AccessControlAllowOriginList
This commit is contained in:
parent
699cf71652
commit
b5198e63c4
11 changed files with 133 additions and 17 deletions
|
@ -306,7 +306,7 @@ The `accessControlAllowOriginList` indicates whether a resource can be shared by
|
||||||
A wildcard origin `*` can also be configured, and will match all requests.
|
A wildcard origin `*` can also be configured, and will match all requests.
|
||||||
If this value is set by a backend server, it will be overwritten by Traefik
|
If this value is set by a backend server, it will be overwritten by Traefik
|
||||||
|
|
||||||
This value can contains a list of allowed origins.
|
This value can contain a list of allowed origins.
|
||||||
|
|
||||||
More information including how to use the settings can be found on:
|
More information including how to use the settings can be found on:
|
||||||
|
|
||||||
|
@ -316,6 +316,14 @@ More information including how to use the settings can be found on:
|
||||||
|
|
||||||
Traefik no longer supports the null value, as it is [no longer recommended as a return value](https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null).
|
Traefik no longer supports the null value, as it is [no longer recommended as a return value](https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null).
|
||||||
|
|
||||||
|
### `accessControlAllowOriginListRegex`
|
||||||
|
|
||||||
|
The `accessControlAllowOriginListRegex` option is the counterpart of the `accessControlAllowOriginList` option with regular expressions instead of origin values.
|
||||||
|
It will allow all origin that contains any match of a regular expression in the `accessControlAllowOriginList`.
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
Regular expressions can be tested using online tools such as [Go Playground](https://play.golang.org/p/mWU9p-wk2ru) or the [Regex101](https://regex101.com/r/58sIgx/2).
|
||||||
|
|
||||||
### `accessControlExposeHeaders`
|
### `accessControlExposeHeaders`
|
||||||
|
|
||||||
The `accessControlExposeHeaders` indicates which headers are safe to expose to the api of a CORS API specification.
|
The `accessControlExposeHeaders` indicates which headers are safe to expose to the api of a CORS API specification.
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
- "traefik.http.middlewares.middleware10.headers.accesscontrolallowmethods=foobar, foobar"
|
- "traefik.http.middlewares.middleware10.headers.accesscontrolallowmethods=foobar, foobar"
|
||||||
- "traefik.http.middlewares.middleware10.headers.accesscontrolalloworigin=foobar"
|
- "traefik.http.middlewares.middleware10.headers.accesscontrolalloworigin=foobar"
|
||||||
- "traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlist=foobar, foobar"
|
- "traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlist=foobar, foobar"
|
||||||
|
- "traefik.http.middlewares.middleware10.headers.accesscontrolalloworiginlistregex=foobar, foobar"
|
||||||
- "traefik.http.middlewares.middleware10.headers.accesscontrolexposeheaders=foobar, foobar"
|
- "traefik.http.middlewares.middleware10.headers.accesscontrolexposeheaders=foobar, foobar"
|
||||||
- "traefik.http.middlewares.middleware10.headers.accesscontrolmaxage=42"
|
- "traefik.http.middlewares.middleware10.headers.accesscontrolmaxage=42"
|
||||||
- "traefik.http.middlewares.middleware10.headers.addvaryheader=true"
|
- "traefik.http.middlewares.middleware10.headers.addvaryheader=true"
|
||||||
|
|
|
@ -153,6 +153,7 @@
|
||||||
accessControlAllowMethods = ["foobar", "foobar"]
|
accessControlAllowMethods = ["foobar", "foobar"]
|
||||||
accessControlAllowOrigin = "foobar"
|
accessControlAllowOrigin = "foobar"
|
||||||
accessControlAllowOriginList = ["foobar", "foobar"]
|
accessControlAllowOriginList = ["foobar", "foobar"]
|
||||||
|
accessControlAllowOriginListRegex = ["foobar", "foobar"]
|
||||||
accessControlExposeHeaders = ["foobar", "foobar"]
|
accessControlExposeHeaders = ["foobar", "foobar"]
|
||||||
accessControlMaxAge = 42
|
accessControlMaxAge = 42
|
||||||
addVaryHeader = true
|
addVaryHeader = true
|
||||||
|
|
|
@ -180,6 +180,9 @@ http:
|
||||||
accessControlAllowOriginList:
|
accessControlAllowOriginList:
|
||||||
- foobar
|
- foobar
|
||||||
- foobar
|
- foobar
|
||||||
|
accessControlAllowOriginListRegex:
|
||||||
|
- foobar
|
||||||
|
- foobar
|
||||||
accessControlExposeHeaders:
|
accessControlExposeHeaders:
|
||||||
- foobar
|
- foobar
|
||||||
- foobar
|
- foobar
|
||||||
|
|
|
@ -45,6 +45,8 @@
|
||||||
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOrigin` | `foobar` |
|
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOrigin` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginList/0` | `foobar` |
|
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginList/0` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginList/1` | `foobar` |
|
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginList/1` | `foobar` |
|
||||||
|
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginListRegex/0` | `foobar` |
|
||||||
|
| `traefik/http/middlewares/Middleware10/headers/accessControlAllowOriginListRegex/1` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware10/headers/accessControlExposeHeaders/0` | `foobar` |
|
| `traefik/http/middlewares/Middleware10/headers/accessControlExposeHeaders/0` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware10/headers/accessControlExposeHeaders/1` | `foobar` |
|
| `traefik/http/middlewares/Middleware10/headers/accessControlExposeHeaders/1` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware10/headers/accessControlMaxAge` | `42` |
|
| `traefik/http/middlewares/Middleware10/headers/accessControlMaxAge` | `42` |
|
||||||
|
|
|
@ -164,6 +164,8 @@ type Headers struct {
|
||||||
AccessControlAllowOrigin string `json:"accessControlAllowOrigin,omitempty" toml:"accessControlAllowOrigin,omitempty" yaml:"accessControlAllowOrigin,omitempty"` // Deprecated
|
AccessControlAllowOrigin string `json:"accessControlAllowOrigin,omitempty" toml:"accessControlAllowOrigin,omitempty" yaml:"accessControlAllowOrigin,omitempty"` // Deprecated
|
||||||
// AccessControlAllowOriginList is a list of allowable origins. Can also be a wildcard origin "*".
|
// AccessControlAllowOriginList is a list of allowable origins. Can also be a wildcard origin "*".
|
||||||
AccessControlAllowOriginList []string `json:"accessControlAllowOriginList,omitempty" toml:"accessControlAllowOriginList,omitempty" yaml:"accessControlAllowOriginList,omitempty"`
|
AccessControlAllowOriginList []string `json:"accessControlAllowOriginList,omitempty" toml:"accessControlAllowOriginList,omitempty" yaml:"accessControlAllowOriginList,omitempty"`
|
||||||
|
// AccessControlAllowOriginListRegex is a list of allowable origins written following the Regular Expression syntax (https://golang.org/pkg/regexp/).
|
||||||
|
AccessControlAllowOriginListRegex []string `json:"accessControlAllowOriginListRegex,omitempty" toml:"accessControlAllowOriginListRegex,omitempty" yaml:"accessControlAllowOriginListRegex,omitempty"`
|
||||||
// AccessControlExposeHeaders sets valid headers for the response.
|
// AccessControlExposeHeaders sets valid headers for the response.
|
||||||
AccessControlExposeHeaders []string `json:"accessControlExposeHeaders,omitempty" toml:"accessControlExposeHeaders,omitempty" yaml:"accessControlExposeHeaders,omitempty"`
|
AccessControlExposeHeaders []string `json:"accessControlExposeHeaders,omitempty" toml:"accessControlExposeHeaders,omitempty" yaml:"accessControlExposeHeaders,omitempty"`
|
||||||
// AccessControlMaxAge sets the time that a preflight request may be cached.
|
// AccessControlMaxAge sets the time that a preflight request may be cached.
|
||||||
|
@ -206,6 +208,7 @@ func (h *Headers) HasCorsHeadersDefined() bool {
|
||||||
len(h.AccessControlAllowHeaders) != 0 ||
|
len(h.AccessControlAllowHeaders) != 0 ||
|
||||||
len(h.AccessControlAllowMethods) != 0 ||
|
len(h.AccessControlAllowMethods) != 0 ||
|
||||||
len(h.AccessControlAllowOriginList) != 0 ||
|
len(h.AccessControlAllowOriginList) != 0 ||
|
||||||
|
len(h.AccessControlAllowOriginListRegex) != 0 ||
|
||||||
len(h.AccessControlExposeHeaders) != 0 ||
|
len(h.AccessControlExposeHeaders) != 0 ||
|
||||||
h.AccessControlMaxAge != 0 ||
|
h.AccessControlMaxAge != 0 ||
|
||||||
h.AddVaryHeader)
|
h.AddVaryHeader)
|
||||||
|
|
|
@ -49,6 +49,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"traefik.http.middlewares.Middleware8.headers.accesscontrolallowmethods": "GET, PUT",
|
"traefik.http.middlewares.Middleware8.headers.accesscontrolallowmethods": "GET, PUT",
|
||||||
"traefik.http.middlewares.Middleware8.headers.accesscontrolalloworigin": "foobar",
|
"traefik.http.middlewares.Middleware8.headers.accesscontrolalloworigin": "foobar",
|
||||||
"traefik.http.middlewares.Middleware8.headers.accesscontrolalloworiginList": "foobar, fiibar",
|
"traefik.http.middlewares.Middleware8.headers.accesscontrolalloworiginList": "foobar, fiibar",
|
||||||
|
"traefik.http.middlewares.Middleware8.headers.accesscontrolalloworiginListRegex": "foobar, fiibar",
|
||||||
"traefik.http.middlewares.Middleware8.headers.accesscontrolexposeheaders": "X-foobar, X-fiibar",
|
"traefik.http.middlewares.Middleware8.headers.accesscontrolexposeheaders": "X-foobar, X-fiibar",
|
||||||
"traefik.http.middlewares.Middleware8.headers.accesscontrolmaxage": "200",
|
"traefik.http.middlewares.Middleware8.headers.accesscontrolmaxage": "200",
|
||||||
"traefik.http.middlewares.Middleware8.headers.addvaryheader": "true",
|
"traefik.http.middlewares.Middleware8.headers.addvaryheader": "true",
|
||||||
|
@ -527,6 +528,10 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
|
AccessControlAllowOriginListRegex: []string{
|
||||||
|
"foobar",
|
||||||
|
"fiibar",
|
||||||
|
},
|
||||||
AccessControlExposeHeaders: []string{
|
AccessControlExposeHeaders: []string{
|
||||||
"X-foobar",
|
"X-foobar",
|
||||||
"X-fiibar",
|
"X-fiibar",
|
||||||
|
@ -999,6 +1004,10 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
|
AccessControlAllowOriginListRegex: []string{
|
||||||
|
"foobar",
|
||||||
|
"fiibar",
|
||||||
|
},
|
||||||
AccessControlExposeHeaders: []string{
|
AccessControlExposeHeaders: []string{
|
||||||
"X-foobar",
|
"X-foobar",
|
||||||
"X-fiibar",
|
"X-fiibar",
|
||||||
|
@ -1155,6 +1164,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlAllowMethods": "GET, PUT",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlAllowMethods": "GET, PUT",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlAllowOrigin": "foobar",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlAllowOrigin": "foobar",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlAllowOriginList": "foobar, fiibar",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlAllowOriginList": "foobar, fiibar",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlAllowOriginListRegex": "foobar, fiibar",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlExposeHeaders": "X-foobar, X-fiibar",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlExposeHeaders": "X-foobar, X-fiibar",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlMaxAge": "200",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.AccessControlMaxAge": "200",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.AddVaryHeader": "true",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.AddVaryHeader": "true",
|
||||||
|
|
|
@ -2,7 +2,9 @@ package headers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -14,26 +16,37 @@ import (
|
||||||
// A single headerOptions struct can be provided to configure which features should be enabled,
|
// A single headerOptions struct can be provided to configure which features should be enabled,
|
||||||
// and the ability to override a few of the default values.
|
// and the ability to override a few of the default values.
|
||||||
type Header struct {
|
type Header struct {
|
||||||
next http.Handler
|
next http.Handler
|
||||||
hasCustomHeaders bool
|
hasCustomHeaders bool
|
||||||
hasCorsHeaders bool
|
hasCorsHeaders bool
|
||||||
headers *dynamic.Headers
|
headers *dynamic.Headers
|
||||||
|
allowOriginRegexes []*regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHeader constructs a new header instance from supplied frontend header struct.
|
// NewHeader constructs a new header instance from supplied frontend header struct.
|
||||||
func NewHeader(next http.Handler, cfg dynamic.Headers) *Header {
|
func NewHeader(next http.Handler, cfg dynamic.Headers) (*Header, error) {
|
||||||
hasCustomHeaders := cfg.HasCustomHeadersDefined()
|
hasCustomHeaders := cfg.HasCustomHeadersDefined()
|
||||||
hasCorsHeaders := cfg.HasCorsHeadersDefined()
|
hasCorsHeaders := cfg.HasCorsHeadersDefined()
|
||||||
|
|
||||||
ctx := log.With(context.Background(), log.Str(log.MiddlewareType, typeName))
|
ctx := log.With(context.Background(), log.Str(log.MiddlewareType, typeName))
|
||||||
handleDeprecation(ctx, &cfg)
|
handleDeprecation(ctx, &cfg)
|
||||||
|
|
||||||
return &Header{
|
regexes := make([]*regexp.Regexp, len(cfg.AccessControlAllowOriginListRegex))
|
||||||
next: next,
|
for i, str := range cfg.AccessControlAllowOriginListRegex {
|
||||||
headers: &cfg,
|
reg, err := regexp.Compile(str)
|
||||||
hasCustomHeaders: hasCustomHeaders,
|
if err != nil {
|
||||||
hasCorsHeaders: hasCorsHeaders,
|
return nil, fmt.Errorf("error occurred during origin parsing: %w", err)
|
||||||
|
}
|
||||||
|
regexes[i] = reg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return &Header{
|
||||||
|
next: next,
|
||||||
|
headers: &cfg,
|
||||||
|
hasCustomHeaders: hasCustomHeaders,
|
||||||
|
hasCorsHeaders: hasCorsHeaders,
|
||||||
|
allowOriginRegexes: regexes,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Header) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (s *Header) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
@ -166,5 +179,11 @@ func (s *Header) isOriginAllowed(origin string) (bool, string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, regex := range s.allowOriginRegexes {
|
||||||
|
if regex.MatchString(origin) {
|
||||||
|
return true, origin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -52,7 +53,8 @@ func TestNewHeader_customRequestHeader(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
mid := NewHeader(emptyHandler, test.cfg)
|
mid, err := NewHeader(emptyHandler, test.cfg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodGet, "/foo", nil)
|
req := httptest.NewRequest(http.MethodGet, "/foo", nil)
|
||||||
req.Header.Set("Foo", "bar")
|
req.Header.Set("Foo", "bar")
|
||||||
|
@ -94,7 +96,8 @@ func TestNewHeader_customRequestHeader_Host(t *testing.T) {
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
mid := NewHeader(emptyHandler, dynamic.Headers{CustomRequestHeaders: test.customHeaders})
|
mid, err := NewHeader(emptyHandler, dynamic.Headers{CustomRequestHeaders: test.customHeaders})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodGet, "http://example.org/foo", nil)
|
req := httptest.NewRequest(http.MethodGet, "http://example.org/foo", nil)
|
||||||
|
|
||||||
|
@ -217,7 +220,8 @@ func TestNewHeader_CORSPreflights(t *testing.T) {
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
mid := NewHeader(emptyHandler, test.cfg)
|
mid, err := NewHeader(emptyHandler, test.cfg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodOptions, "/foo", nil)
|
req := httptest.NewRequest(http.MethodOptions, "/foo", nil)
|
||||||
req.Header = test.requestHeaders
|
req.Header = test.requestHeaders
|
||||||
|
@ -240,6 +244,7 @@ func TestNewHeader_CORSResponses(t *testing.T) {
|
||||||
cfg dynamic.Headers
|
cfg dynamic.Headers
|
||||||
requestHeaders http.Header
|
requestHeaders http.Header
|
||||||
expected http.Header
|
expected http.Header
|
||||||
|
expectedError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "Test Simple Request",
|
desc: "Test Simple Request",
|
||||||
|
@ -267,6 +272,54 @@ func TestNewHeader_CORSResponses(t *testing.T) {
|
||||||
"Access-Control-Allow-Origin": {"*"},
|
"Access-Control-Allow-Origin": {"*"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Regexp Origin Request",
|
||||||
|
next: emptyHandler,
|
||||||
|
cfg: dynamic.Headers{
|
||||||
|
AccessControlAllowOriginListRegex: []string{"^https?://([a-z]+)\\.bar\\.org$"},
|
||||||
|
},
|
||||||
|
requestHeaders: map[string][]string{
|
||||||
|
"Origin": {"https://foo.bar.org"},
|
||||||
|
},
|
||||||
|
expected: map[string][]string{
|
||||||
|
"Access-Control-Allow-Origin": {"https://foo.bar.org"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Partial Regexp Origin Request",
|
||||||
|
next: emptyHandler,
|
||||||
|
cfg: dynamic.Headers{
|
||||||
|
AccessControlAllowOriginListRegex: []string{"([a-z]+)\\.bar"},
|
||||||
|
},
|
||||||
|
requestHeaders: map[string][]string{
|
||||||
|
"Origin": {"https://foo.bar.org"},
|
||||||
|
},
|
||||||
|
expected: map[string][]string{
|
||||||
|
"Access-Control-Allow-Origin": {"https://foo.bar.org"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Regexp Malformed Origin Request",
|
||||||
|
next: emptyHandler,
|
||||||
|
cfg: dynamic.Headers{
|
||||||
|
AccessControlAllowOriginListRegex: []string{"a(b"},
|
||||||
|
},
|
||||||
|
requestHeaders: map[string][]string{
|
||||||
|
"Origin": {"https://foo.bar.org"},
|
||||||
|
},
|
||||||
|
expectedError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Regexp Origin Request without matching",
|
||||||
|
next: emptyHandler,
|
||||||
|
cfg: dynamic.Headers{
|
||||||
|
AccessControlAllowOriginListRegex: []string{"([a-z]+)\\.bar\\.org"},
|
||||||
|
},
|
||||||
|
requestHeaders: map[string][]string{
|
||||||
|
"Origin": {"https://bar.org"},
|
||||||
|
},
|
||||||
|
expected: map[string][]string{},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Empty origin Request",
|
desc: "Empty origin Request",
|
||||||
next: emptyHandler,
|
next: emptyHandler,
|
||||||
|
@ -416,7 +469,12 @@ func TestNewHeader_CORSResponses(t *testing.T) {
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
mid := NewHeader(test.next, test.cfg)
|
mid, err := NewHeader(test.next, test.cfg)
|
||||||
|
if test.expectedError {
|
||||||
|
require.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodGet, "/foo", nil)
|
req := httptest.NewRequest(http.MethodGet, "/foo", nil)
|
||||||
req.Header = test.requestHeaders
|
req.Header = test.requestHeaders
|
||||||
|
@ -478,7 +536,8 @@ func TestNewHeader_customResponseHeaders(t *testing.T) {
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
mid := NewHeader(emptyHandler, dynamic.Headers{CustomResponseHeaders: test.config})
|
mid, err := NewHeader(emptyHandler, dynamic.Headers{CustomResponseHeaders: test.config})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodGet, "/foo", nil)
|
req := httptest.NewRequest(http.MethodGet, "/foo", nil)
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,11 @@ func New(ctx context.Context, next http.Handler, cfg dynamic.Headers, name strin
|
||||||
|
|
||||||
if hasCustomHeaders || hasCorsHeaders {
|
if hasCustomHeaders || hasCorsHeaders {
|
||||||
logger.Debugf("Setting up customHeaders/Cors from %v", cfg)
|
logger.Debugf("Setting up customHeaders/Cors from %v", cfg)
|
||||||
handler = NewHeader(nextHandler, cfg)
|
var err error
|
||||||
|
handler, err = NewHeader(nextHandler, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &headers{
|
return &headers{
|
||||||
|
|
|
@ -100,6 +100,8 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"traefik/http/middlewares/Middleware09/headers/accessControlAllowOrigin": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/accessControlAllowOrigin": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/accessControlAllowOriginList/0": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/accessControlAllowOriginList/0": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/accessControlAllowOriginList/1": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/accessControlAllowOriginList/1": "foobar",
|
||||||
|
"traefik/http/middlewares/Middleware09/headers/accessControlAllowOriginListRegex/0": "foobar",
|
||||||
|
"traefik/http/middlewares/Middleware09/headers/accessControlAllowOriginListRegex/1": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/contentTypeNosniff": "true",
|
"traefik/http/middlewares/Middleware09/headers/contentTypeNosniff": "true",
|
||||||
"traefik/http/middlewares/Middleware09/headers/accessControlAllowCredentials": "true",
|
"traefik/http/middlewares/Middleware09/headers/accessControlAllowCredentials": "true",
|
||||||
"traefik/http/middlewares/Middleware09/headers/featurePolicy": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/featurePolicy": "foobar",
|
||||||
|
@ -557,6 +559,10 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"foobar",
|
"foobar",
|
||||||
},
|
},
|
||||||
|
AccessControlAllowOriginListRegex: []string{
|
||||||
|
"foobar",
|
||||||
|
"foobar",
|
||||||
|
},
|
||||||
AccessControlExposeHeaders: []string{
|
AccessControlExposeHeaders: []string{
|
||||||
"foobar",
|
"foobar",
|
||||||
"foobar",
|
"foobar",
|
||||||
|
|
Loading…
Reference in a new issue