diff --git a/docs/content/contributing/submitting-pull-requests.md b/docs/content/contributing/submitting-pull-requests.md index c171d9fea..bb3183f40 100644 --- a/docs/content/contributing/submitting-pull-requests.md +++ b/docs/content/contributing/submitting-pull-requests.md @@ -42,4 +42,4 @@ Help the readers focus on what matters, and help them understand the structure o !!! tip "10 Tips for Better Pull Requests" - We enjoyed this article, maybe you will too! [10 tips for better pull requests](http://blog.ploeh.dk/2015/01/15/10-tips-for-better-pull-requests/). + We enjoyed this article, maybe you will too! [10 tips for better pull requests](https://blog.ploeh.dk/2015/01/15/10-tips-for-better-pull-requests/). diff --git a/integration/fixtures/file/simple-hosts.toml b/integration/fixtures/file/simple-hosts.toml new file mode 100644 index 000000000..b8cd6b2b3 --- /dev/null +++ b/integration/fixtures/file/simple-hosts.toml @@ -0,0 +1,28 @@ +[global] +checkNewVersion = false +sendAnonymousUsage = false + +[log] +level = "DEBUG" + +[entryPoints] + [entryPoints.web] + address = ":8000" + +[providers] + [providers.file] + +[http.routers] + [http.routers.router1] + rule = "Host(`test.localhost`)" + service = "service1" + + [http.routers.router2] + rule = "Host(`test.foo.localhost.`)" + service = "service1" + +[http.services] + [http.services.service1.loadbalancer] + [[http.services.service1.loadbalancer.servers]] + URL = "{{.Server}}" + weight = 10 diff --git a/integration/simple_test.go b/integration/simple_test.go index e0d72ad04..2ae6e7d30 100644 --- a/integration/simple_test.go +++ b/integration/simple_test.go @@ -481,3 +481,54 @@ func (s *SimpleSuite) TestMultiprovider(c *check.C) { c.Assert(err, checker.IsNil) } + +func (s *SimpleSuite) TestSimpleConfigurationHostRequestTrailingPeriod(c *check.C) { + s.createComposeProject(c, "base") + s.composeProject.Start(c) + + server := "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + + file := s.adaptFile(c, "fixtures/file/simple-hosts.toml", struct { + Server string + }{Server: server}) + defer os.Remove(file) + + cmd, output := s.traefikCmd(withConfigFile(file)) + defer output(c) + + err := cmd.Start() + c.Assert(err, checker.IsNil) + defer cmd.Process.Kill() + + testCases := []struct { + desc string + requestHost string + }{ + { + desc: "Request host without trailing period, rule without trailing period", + requestHost: "test.localhost", + }, + { + desc: "Request host with trailing period, rule without trailing period", + requestHost: "test.localhost.", + }, + { + desc: "Request host without trailing period, rule with trailing period", + requestHost: "test.foo.localhost", + }, + { + desc: "Request host with trailing period, rule with trailing period", + requestHost: "test.foo.localhost.", + }, + } + + for _, test := range testCases { + req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000", nil) + c.Assert(err, checker.IsNil) + req.Host = test.requestHost + err = try.Request(req, 1*time.Second, try.StatusCodeIs(http.StatusOK)) + if err != nil { + c.Fatalf("Error while testing %s: %v", test.desc, err) + } + } +} diff --git a/pkg/rules/rules.go b/pkg/rules/rules.go index e57d17ab6..36458f4f7 100644 --- a/pkg/rules/rules.go +++ b/pkg/rules/rules.go @@ -119,6 +119,22 @@ func host(route *mux.Route, hosts ...string) error { if reqHost == host { return true } + + // Check for match on trailing period on host + if last := len(host) - 1; last >= 0 && host[last] == '.' { + h := host[:last] + if reqHost == h { + return true + } + } + + // Check for match on trailing period on request + if last := len(reqHost) - 1; last >= 0 && reqHost[last] == '.' { + h := reqHost[:last] + if h == host { + return true + } + } } return false }) diff --git a/pkg/rules/rules_test.go b/pkg/rules/rules_test.go index 348c3af97..3f459f2a2 100644 --- a/pkg/rules/rules_test.go +++ b/pkg/rules/rules_test.go @@ -50,6 +50,27 @@ func Test_addRoute(t *testing.T) { "http://localhost/foo": http.StatusOK, }, }, + { + desc: "Host with trailing period in rule", + rule: "Host(`localhost.`)", + expected: map[string]int{ + "http://localhost/foo": http.StatusOK, + }, + }, + { + desc: "Host with trailing period in domain", + rule: "Host(`localhost`)", + expected: map[string]int{ + "http://localhost./foo": http.StatusOK, + }, + }, + { + desc: "Host with trailing period in domain and rule", + rule: "Host(`localhost.`)", + expected: map[string]int{ + "http://localhost./foo": http.StatusOK, + }, + }, { desc: "wrong Host", rule: "Host(`nope`)",