diff --git a/provider/acme/provider.go b/provider/acme/provider.go index 8ff0a1c2c..3f43eaf91 100644 --- a/provider/acme/provider.go +++ b/provider/acme/provider.go @@ -338,7 +338,7 @@ func (p *Provider) watchNewDomains() { } if len(domains) == 0 { - log.Debugf("No domain parsed in rule %q", route.Rule) + log.Debugf("No domain parsed in rule %q in provider ACME", route.Rule) continue } diff --git a/rules/rules.go b/rules/rules.go index 4a5658cd7..093d031d1 100644 --- a/rules/rules.go +++ b/rules/rules.go @@ -8,7 +8,6 @@ import ( "sort" "strings" - "github.com/BurntSushi/ty/fun" "github.com/containous/mux" "github.com/containous/traefik/hostresolver" "github.com/containous/traefik/log" @@ -288,9 +287,11 @@ func (r *Rules) Parse(expression string) (*mux.Route, error) { // ParseDomains parses rules expressions and returns domains func (r *Rules) ParseDomains(expression string) ([]string, error) { var domains []string + isHostRule := false err := r.parseRules(expression, func(functionName string, function interface{}, arguments []string) error { if functionName == "Host" { + isHostRule = true domains = append(domains, arguments...) } return nil @@ -299,5 +300,18 @@ func (r *Rules) ParseDomains(expression string) ([]string, error) { return nil, fmt.Errorf("error parsing domains: %v", err) } - return fun.Map(strings.ToLower, domains).([]string), nil + var cleanDomains []string + for _, domain := range domains { + canonicalDomain := strings.ToLower(domain) + if len(canonicalDomain) > 0 { + cleanDomains = append(cleanDomains, canonicalDomain) + } + } + + // Return an error if an Host rule is detected but no domain are parsed + if isHostRule && len(cleanDomains) == 0 { + return nil, fmt.Errorf("unable to parse correctly the domains in the Host rule from %q", expression) + } + + return cleanDomains, nil } diff --git a/rules/rules_test.go b/rules/rules_test.go index 7578cedca..0db618218 100644 --- a/rules/rules_test.go +++ b/rules/rules_test.go @@ -64,24 +64,38 @@ func TestParseDomains(t *testing.T) { rules := &Rules{} tests := []struct { - expression string - domain []string + description string + expression string + domain []string + errorExpected bool }{ { - expression: "Host:foo.bar,test.bar", - domain: []string{"foo.bar", "test.bar"}, + description: "Many host rules", + expression: "Host:foo.bar,test.bar", + domain: []string{"foo.bar", "test.bar"}, + errorExpected: false, }, { - expression: "Path:/test", - domain: []string{}, + description: "No host rule", + expression: "Path:/test", + errorExpected: false, }, { - expression: "Host:foo.bar;Path:/test", - domain: []string{"foo.bar"}, + description: "Host rule and another rule", + expression: "Host:foo.bar;Path:/test", + domain: []string{"foo.bar"}, + errorExpected: false, }, { - expression: "Host: Foo.Bar ;Path:/test", - domain: []string{"foo.bar"}, + description: "Host rule to trim and another rule", + expression: "Host: Foo.Bar ;Path:/test", + domain: []string{"foo.bar"}, + errorExpected: false, + }, + { + description: "Host rule with no domain", + expression: "Host: ;Path:/test", + errorExpected: true, }, } @@ -91,7 +105,12 @@ func TestParseDomains(t *testing.T) { t.Parallel() domains, err := rules.ParseDomains(test.expression) - require.NoError(t, err, "%s: Error while parsing domain.", test.expression) + + if test.errorExpected { + require.Errorf(t, err, "unable to parse correctly the domains in the Host rule from %q", test.expression) + } else { + require.NoError(t, err, "%s: Error while parsing domain.", test.expression) + } assert.EqualValues(t, test.domain, domains, "%s: Error parsing domains from expression.", test.expression) }) diff --git a/server/server_configuration.go b/server/server_configuration.go index 773eb8be0..a9e5b0e59 100644 --- a/server/server_configuration.go +++ b/server/server_configuration.go @@ -540,6 +540,8 @@ func (s *Server) postLoadConfiguration() { domains, err := rls.ParseDomains(route.Rule) if err != nil { log.Errorf("Error parsing domains: %v", err) + } else if len(domains) == 0 { + log.Debugf("No domain parsed in rule %q", route.Rule) } else { s.globalConfiguration.ACME.LoadCertificateForDomains(domains) }