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

@ -0,0 +1,21 @@
[entrypoints]
[entrypoints.web]
address = ":8000"
[log]
logLevel = "DEBUG"
[providers]
[providers.file]
[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"
weight = 1

View file

@ -0,0 +1,28 @@
[entrypoints]
[entrypoints.web]
address = ":8000"
[log]
logLevel = "DEBUG"
[providers]
[providers.file]
[http.routers]
[http.routers.router1]
rule = "Host(`test.localhost`)"
service = "service1"
[http.middlewares]
[http.middlewares.cors.Headers]
AccessControlAllowMethods= ["GET", "OPTIONS", "PUT"]
AccessControlAllowOrigin = "origin-list-or-null"
AccessControlMaxAge = 100
AddVaryHeader = true
[http.services]
[http.services.service1.loadbalancer]
[[http.services.service1.loadbalancer.servers]]
url = "http://172.17.0.2:80"
weight = 1

106
integration/headers_test.go Normal file
View file

@ -0,0 +1,106 @@
package integration
import (
"net/http"
"time"
"github.com/containous/traefik/integration/try"
"github.com/go-check/check"
checker "github.com/vdemeester/shakers"
)
// 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)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
// Expected a 404 as we did not configure anything
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
c.Assert(err, checker.IsNil)
}
func (s *HeadersSuite) TestCorsResponses(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 access control allow origin",
requestHeaders: http.Header{
"Origin": {"https://foo.bar.org"},
},
expected: http.Header{
"Access-Control-Allow-Origin": {"https://foo.bar.org"},
"Vary": {"Origin"},
},
},
}
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{
"Access-Control-Request-Headers": {"origin"},
"Access-Control-Request-Method": {"GET", "OPTIONS"},
"Origin": {"https://foo.bar.org"},
},
expected: http.Header{
"Access-Control-Allow-Origin": {"https://foo.bar.org"},
"Access-Control-Max-Age": {"100"},
"Access-Control-Allow-Methods": {"GET,OPTIONS,PUT"},
},
},
}
for _, test := range testCase {
req, err := http.NewRequest(http.MethodOptions, "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)
}
}

View file

@ -45,6 +45,7 @@ func init() {
check.Suite(&FileSuite{})
check.Suite(&GRPCSuite{})
check.Suite(&HealthCheckSuite{})
check.Suite(&HeadersSuite{})
check.Suite(&HostResolverSuite{})
check.Suite(&HTTPSSuite{})
check.Suite(&LogRotationSuite{})

View file

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

View file

@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
"reflect"
"strings"
"github.com/abronan/valkeyrie/store"
@ -125,6 +126,62 @@ func StatusCodeIs(status int) ResponseCondition {
}
}
// HasHeader returns a retry condition function.
// The condition returns an error if the response does not have a header set.
func HasHeader(header string) ResponseCondition {
return func(res *http.Response) error {
if _, ok := res.Header[header]; !ok {
return errors.New("response doesn't contain header: " + header)
}
return nil
}
}
// HasHeaderValue returns a retry condition function.
// The condition returns an error if the response does not have a header set, and a value for that header.
// Has an option to test for an exact header match only, not just contains.
func HasHeaderValue(header, value string, exactMatch bool) ResponseCondition {
return func(res *http.Response) error {
if _, ok := res.Header[header]; !ok {
return errors.New("response doesn't contain header: " + header)
}
matchFound := false
for _, hdr := range res.Header[header] {
if value != hdr && exactMatch {
return fmt.Errorf("got header %s with value %s, wanted %s", header, hdr, value)
}
if value == hdr {
matchFound = true
}
}
if !matchFound {
return fmt.Errorf("response doesn't contain header %s with value %s", header, value)
}
return nil
}
}
// HasHeaderStruct returns a retry condition function.
// The condition returns an error if the response does contain the headers set, and matching contents.
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])
}
}
}
return nil
}
}
// DoCondition is a retry condition function.
// It returns an error
type DoCondition func() error