Properly add response headers for CORS

This commit is contained in:
Daniel Tomcej 2019-07-12 03:46:04 -06:00 committed by Traefiker Bot
parent 74c5ec70a9
commit 3f6ea04048
8 changed files with 198 additions and 138 deletions

View file

@ -8,18 +8,3 @@
[entryPoints]
[entryPoints.web]
address = ":8000"
[providers]
[providers.file]
## dynamic configuration ##
[http.routers]
[http.routers.router1]
rule = "Host(`test.localhost`)"
service = "service1"
[http.services]
[http.services.service1.loadBalancer]
[[http.services.service1.loadBalancer.servers]]
url = "http://172.17.0.2:80"

View file

@ -17,6 +17,12 @@
[http.routers]
[http.routers.router1]
rule = "Host(`test.localhost`)"
middlewares = ["cors"]
service = "service1"
[http.routers.router2]
rule = "Host(`test2.localhost`)"
middlewares = ["nocors"]
service = "service1"
[http.middlewares]
@ -26,7 +32,11 @@
accessControlMaxAge = 100
addVaryHeader = true
[http.middlewares.nocors.Headers]
[http.middlewares.nocors.Headers.CustomResponseHeaders]
X-Custom-Response-Header = "True"
[http.services]
[http.services.service1.loadBalancer]
[[http.services.service1.loadBalancer.servers]]
url = "http://172.17.0.2:80"
url = "http://127.0.0.1:9000"

View file

@ -12,12 +12,6 @@ import (
// Headers test suites
type HeadersSuite struct{ BaseSuite }
func (s *HeadersSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "headers")
s.composeProject.Start(c)
}
func (s *HeadersSuite) TestSimpleConfiguration(c *check.C) {
cmd, display := s.traefikCmd(withConfigFile("fixtures/headers/basic.toml"))
defer display(c)
@ -38,10 +32,18 @@ func (s *HeadersSuite) TestCorsResponses(c *check.C) {
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
backend := startTestServer("9000", http.StatusOK)
defer backend.Close()
err = try.GetRequest(backend.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
testCase := []struct {
desc string
requestHeaders http.Header
expected http.Header
reqHost string
method string
}{
{
desc: "simple access control allow origin",
@ -52,33 +54,9 @@ func (s *HeadersSuite) TestCorsResponses(c *check.C) {
"Access-Control-Allow-Origin": {"https://foo.bar.org"},
"Vary": {"Origin"},
},
reqHost: "test.localhost",
method: http.MethodGet,
},
}
for _, test := range testCase {
req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.localhost"
req.Header = test.requestHeaders
err = try.Request(req, 500*time.Millisecond, try.HasBody(), try.HasHeaderStruct(test.expected))
c.Assert(err, checker.IsNil)
}
}
func (s *HeadersSuite) TestCorsPreflightResponses(c *check.C) {
cmd, display := s.traefikCmd(withConfigFile("fixtures/headers/cors.toml"))
defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
testCase := []struct {
desc string
requestHeaders http.Header
expected http.Header
}{
{
desc: "simple preflight request",
requestHeaders: http.Header{
@ -91,16 +69,44 @@ func (s *HeadersSuite) TestCorsPreflightResponses(c *check.C) {
"Access-Control-Max-Age": {"100"},
"Access-Control-Allow-Methods": {"GET,OPTIONS,PUT"},
},
reqHost: "test.localhost",
method: http.MethodOptions,
},
{
desc: "preflight Options request with no cors configured",
requestHeaders: http.Header{
"Access-Control-Request-Headers": {"origin"},
"Access-Control-Request-Method": {"GET", "OPTIONS"},
"Origin": {"https://foo.bar.org"},
},
expected: http.Header{
"X-Custom-Response-Header": {"True"},
},
reqHost: "test2.localhost",
method: http.MethodOptions,
},
{
desc: "preflight Get request with no cors configured",
requestHeaders: http.Header{
"Access-Control-Request-Headers": {"origin"},
"Access-Control-Request-Method": {"GET", "OPTIONS"},
"Origin": {"https://foo.bar.org"},
},
expected: http.Header{
"X-Custom-Response-Header": {"True"},
},
reqHost: "test2.localhost",
method: http.MethodGet,
},
}
for _, test := range testCase {
req, err := http.NewRequest(http.MethodOptions, "http://127.0.0.1:8000/", nil)
req, err := http.NewRequest(test.method, "http://127.0.0.1:8000/", nil)
c.Assert(err, checker.IsNil)
req.Host = "test.localhost"
req.Host = test.reqHost
req.Header = test.requestHeaders
err = try.Request(req, 500*time.Millisecond, try.HasBody(), try.HasHeaderStruct(test.expected))
err = try.Request(req, 500*time.Millisecond, try.HasHeaderStruct(test.expected))
c.Assert(err, checker.IsNil)
}
}

View file

@ -1,4 +0,0 @@
whoami1:
image: containous/whoami
ports:
- "8881:80"

View file

@ -168,18 +168,17 @@ func HasHeaderValue(header, value string, exactMatch bool) ResponseCondition {
func HasHeaderStruct(header http.Header) ResponseCondition {
return func(res *http.Response) error {
for key := range header {
if _, ok := res.Header[key]; ok {
// Header exists in the response, test it.
eq := reflect.DeepEqual(header[key], res.Header[key])
if !eq {
return fmt.Errorf("for header %s got values %v, wanted %v", key, res.Header[key], header[key])
}
if _, ok := res.Header[key]; !ok {
return fmt.Errorf("header %s not present in the response. Expected headers: %v Got response headers: %v", key, header, res.Header)
}
// Header exists in the response, test it.
if !reflect.DeepEqual(header[key], res.Header[key]) {
return fmt.Errorf("for header %s got values %v, wanted %v", key, res.Header[key], header[key])
}
}
return nil
}
}
// DoCondition is a retry condition function.