1
0
Fork 0

Enable CORS configuration

This commit is contained in:
Daniel Tomcej 2019-04-02 03:40:04 -05:00 committed by Traefiker Bot
parent 883f90dded
commit d2b38e6ac4
13 changed files with 888 additions and 89 deletions

View file

@ -10,6 +10,7 @@ import (
"github.com/containous/traefik/pkg/config"
"github.com/containous/traefik/pkg/testhelpers"
"github.com/containous/traefik/pkg/tracing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -17,7 +18,7 @@ import (
func TestCustomRequestHeader(t *testing.T) {
emptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
header := newHeader(emptyHandler, config.Headers{
header := NewHeader(emptyHandler, config.Headers{
CustomRequestHeaders: map[string]string{
"X-Custom-Request-Header": "test_request",
},
@ -35,7 +36,7 @@ func TestCustomRequestHeader(t *testing.T) {
func TestCustomRequestHeaderEmptyValue(t *testing.T) {
emptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
header := newHeader(emptyHandler, config.Headers{
header := NewHeader(emptyHandler, config.Headers{
CustomRequestHeaders: map[string]string{
"X-Custom-Request-Header": "test_request",
},
@ -49,7 +50,7 @@ func TestCustomRequestHeaderEmptyValue(t *testing.T) {
assert.Equal(t, http.StatusOK, res.Code)
assert.Equal(t, "test_request", req.Header.Get("X-Custom-Request-Header"))
header = newHeader(emptyHandler, config.Headers{
header = NewHeader(emptyHandler, config.Headers{
CustomRequestHeaders: map[string]string{
"X-Custom-Request-Header": "",
},
@ -188,3 +189,312 @@ func TestSSLForceHost(t *testing.T) {
})
}
}
func TestCORSPreflights(t *testing.T) {
emptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
testCases := []struct {
desc string
header *Header
requestHeaders http.Header
expected http.Header
}{
{
desc: "Test Simple Preflight",
header: NewHeader(emptyHandler, config.Headers{
AccessControlAllowMethods: []string{"GET", "OPTIONS", "PUT"},
AccessControlAllowOrigin: "origin-list-or-null",
AccessControlMaxAge: 600,
}),
requestHeaders: map[string][]string{
"Access-Control-Request-Headers": {"origin"},
"Access-Control-Request-Method": {"GET", "OPTIONS"},
"Origin": {"https://foo.bar.org"},
},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"https://foo.bar.org"},
"Access-Control-Max-Age": {"600"},
"Access-Control-Allow-Methods": {"GET,OPTIONS,PUT"},
},
},
{
desc: "Wildcard origin Preflight",
header: NewHeader(emptyHandler, config.Headers{
AccessControlAllowMethods: []string{"GET", "OPTIONS", "PUT"},
AccessControlAllowOrigin: "*",
AccessControlMaxAge: 600,
}),
requestHeaders: map[string][]string{
"Access-Control-Request-Headers": {"origin"},
"Access-Control-Request-Method": {"GET", "OPTIONS"},
"Origin": {"https://foo.bar.org"},
},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Max-Age": {"600"},
"Access-Control-Allow-Methods": {"GET,OPTIONS,PUT"},
},
},
{
desc: "Allow Credentials Preflight",
header: NewHeader(emptyHandler, config.Headers{
AccessControlAllowMethods: []string{"GET", "OPTIONS", "PUT"},
AccessControlAllowOrigin: "*",
AccessControlAllowCredentials: true,
AccessControlMaxAge: 600,
}),
requestHeaders: map[string][]string{
"Access-Control-Request-Headers": {"origin"},
"Access-Control-Request-Method": {"GET", "OPTIONS"},
"Origin": {"https://foo.bar.org"},
},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Max-Age": {"600"},
"Access-Control-Allow-Methods": {"GET,OPTIONS,PUT"},
"Access-Control-Allow-Credentials": {"true"},
},
},
{
desc: "Allow Headers Preflight",
header: NewHeader(emptyHandler, config.Headers{
AccessControlAllowMethods: []string{"GET", "OPTIONS", "PUT"},
AccessControlAllowOrigin: "*",
AccessControlAllowHeaders: []string{"origin", "X-Forwarded-For"},
AccessControlMaxAge: 600,
}),
requestHeaders: map[string][]string{
"Access-Control-Request-Headers": {"origin"},
"Access-Control-Request-Method": {"GET", "OPTIONS"},
"Origin": {"https://foo.bar.org"},
},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Max-Age": {"600"},
"Access-Control-Allow-Methods": {"GET,OPTIONS,PUT"},
"Access-Control-Allow-Headers": {"origin,X-Forwarded-For"},
},
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
req := testhelpers.MustNewRequest(http.MethodOptions, "/foo", nil)
req.Header = test.requestHeaders
rw := httptest.NewRecorder()
test.header.ServeHTTP(rw, req)
assert.Equal(t, test.expected, rw.Result().Header)
})
}
}
func TestEmptyHeaderObject(t *testing.T) {
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
_, err := New(context.Background(), next, config.Headers{}, "testing")
require.Errorf(t, err, "headers configuration not valid")
}
func TestCustomHeaderHandler(t *testing.T) {
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
header, _ := New(context.Background(), next, config.Headers{
CustomRequestHeaders: map[string]string{
"X-Custom-Request-Header": "test_request",
},
}, "testing")
res := httptest.NewRecorder()
req := testhelpers.MustNewRequest(http.MethodGet, "/foo", nil)
header.ServeHTTP(res, req)
assert.Equal(t, http.StatusOK, res.Code)
assert.Equal(t, "test_request", req.Header.Get("X-Custom-Request-Header"))
}
func TestGetTracingInformation(t *testing.T) {
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
header := &headers{
handler: next,
name: "testing",
}
name, trace := header.GetTracingInformation()
assert.Equal(t, "testing", name)
assert.Equal(t, tracing.SpanKindNoneEnum, trace)
}
func TestCORSResponses(t *testing.T) {
emptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
nonEmptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Vary", "Testing") })
testCases := []struct {
desc string
header *Header
requestHeaders http.Header
expected http.Header
}{
{
desc: "Test Simple Request",
header: NewHeader(emptyHandler, config.Headers{
AccessControlAllowOrigin: "origin-list-or-null",
}),
requestHeaders: map[string][]string{
"Origin": {"https://foo.bar.org"},
},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"https://foo.bar.org"},
},
},
{
desc: "Wildcard origin Request",
header: NewHeader(emptyHandler, config.Headers{
AccessControlAllowOrigin: "*",
}),
requestHeaders: map[string][]string{
"Origin": {"https://foo.bar.org"},
},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"*"},
},
},
{
desc: "Empty origin Request",
header: NewHeader(emptyHandler, config.Headers{
AccessControlAllowOrigin: "origin-list-or-null",
}),
requestHeaders: map[string][]string{},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"null"},
},
},
{
desc: "Not Defined origin Request",
header: NewHeader(emptyHandler, config.Headers{}),
requestHeaders: map[string][]string{},
expected: map[string][]string{},
},
{
desc: "Allow Credentials Request",
header: NewHeader(emptyHandler, config.Headers{
AccessControlAllowOrigin: "*",
AccessControlAllowCredentials: true,
}),
requestHeaders: map[string][]string{
"Origin": {"https://foo.bar.org"},
},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Allow-Credentials": {"true"},
},
},
{
desc: "Expose Headers Request",
header: NewHeader(emptyHandler, config.Headers{
AccessControlAllowOrigin: "*",
AccessControlExposeHeaders: []string{"origin", "X-Forwarded-For"},
}),
requestHeaders: map[string][]string{
"Origin": {"https://foo.bar.org"},
},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"*"},
"Access-Control-Expose-Headers": {"origin,X-Forwarded-For"},
},
},
{
desc: "Test Simple Request with Vary Headers",
header: NewHeader(emptyHandler, config.Headers{
AccessControlAllowOrigin: "origin-list-or-null",
AddVaryHeader: true,
}),
requestHeaders: map[string][]string{
"Origin": {"https://foo.bar.org"},
},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"https://foo.bar.org"},
"Vary": {"Origin"},
},
},
{
desc: "Test Simple Request with Vary Headers and non-empty response",
header: NewHeader(nonEmptyHandler, config.Headers{
AccessControlAllowOrigin: "origin-list-or-null",
AddVaryHeader: true,
}),
requestHeaders: map[string][]string{
"Origin": {"https://foo.bar.org"},
},
expected: map[string][]string{
"Access-Control-Allow-Origin": {"https://foo.bar.org"},
"Vary": {"Testing,Origin"},
},
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
req := testhelpers.MustNewRequest(http.MethodGet, "/foo", nil)
req.Header = test.requestHeaders
rw := httptest.NewRecorder()
test.header.ServeHTTP(rw, req)
err := test.header.ModifyResponseHeaders(rw.Result())
require.NoError(t, err)
assert.Equal(t, test.expected, rw.Result().Header)
})
}
}
func TestCustomResponseHeaders(t *testing.T) {
emptyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
testCases := []struct {
desc string
header *Header
expected http.Header
}{
{
desc: "Test Simple Response",
header: NewHeader(emptyHandler, config.Headers{
CustomResponseHeaders: map[string]string{
"Testing": "foo",
"Testing2": "bar",
},
}),
expected: map[string][]string{
"Testing": {"foo"},
"Testing2": {"bar"},
},
},
{
desc: "Deleting Custom Header",
header: NewHeader(emptyHandler, config.Headers{
CustomResponseHeaders: map[string]string{
"Testing": "foo",
"Testing2": "",
},
}),
expected: map[string][]string{
"Testing": {"foo"},
},
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
req := testhelpers.MustNewRequest(http.MethodGet, "/foo", nil)
rw := httptest.NewRecorder()
test.header.ServeHTTP(rw, req)
err := test.header.ModifyResponseHeaders(rw.Result())
require.NoError(t, err)
assert.Equal(t, test.expected, rw.Result().Header)
})
}
}