diff --git a/provider/kubernetes/fixtures/ingressAnnotations_ingresses.yml b/provider/kubernetes/fixtures/ingressAnnotations_ingresses.yml index 7a39fc6aa..8b9b37e78 100644 --- a/provider/kubernetes/fixtures/ingressAnnotations_ingresses.yml +++ b/provider/kubernetes/fixtures/ingressAnnotations_ingresses.yml @@ -161,6 +161,23 @@ spec: servicePort: 80 path: /api +--- + apiVersion: extensions/v1beta1 + kind: Ingress + metadata: + annotations: + ingress.kubernetes.io/rewrite-target: /app + namespace: testing + spec: + rules: + - host: rewritetargetrootpath + http: + paths: + - backend: + serviceName: service1 + servicePort: 80 + path: / + --- apiVersion: extensions/v1beta1 kind: Ingress diff --git a/provider/kubernetes/kubernetes.go b/provider/kubernetes/kubernetes.go index 4145354ad..d7899ac15 100644 --- a/provider/kubernetes/kubernetes.go +++ b/provider/kubernetes/kubernetes.go @@ -674,6 +674,12 @@ func getRuleForPath(pa extensionsv1beta1.HTTPIngressPath, i *extensionsv1beta1.I return "", fmt.Errorf("rewrite-target must not be used together with annotation %q", annotationKubernetesRuleType) } rewriteTargetRule := fmt.Sprintf("ReplacePathRegex: ^%s(.*) %s$1", pa.Path, strings.TrimRight(rewriteTarget, "/")) + if pa.Path == "/" { + // If path = /, then just append the cap group, as if we don't cap the path as part of the regex, + // then when we strip the right / from the rewrite target, it ends up being missed, as removed but never returned + // this only happens when path = / because it is the only case where TrimRight will catch a leading /. + rewriteTargetRule = fmt.Sprintf("ReplacePathRegex: ^(.*) %s$1", strings.TrimRight(rewriteTarget, "/")) + } rules = append(rules, rewriteTargetRule) } diff --git a/provider/kubernetes/kubernetes_test.go b/provider/kubernetes/kubernetes_test.go index 99367c898..bac7ae84a 100644 --- a/provider/kubernetes/kubernetes_test.go +++ b/provider/kubernetes/kubernetes_test.go @@ -415,6 +415,12 @@ func TestProvider_loadIngresses(t *testing.T) { server("http://example.com", weight(1))), lbMethod("wrr"), ), + backend("rewritetargetrootpath/", + servers( + server("http://example.com", weight(1)), + server("http://example.com", weight(1))), + lbMethod("wrr"), + ), backend("error-pages/errorpages", servers( server("http://example.com", weight(1)), @@ -523,6 +529,12 @@ func TestProvider_loadIngresses(t *testing.T) { route("/whitelist-source-range", "PathPrefix:/whitelist-source-range"), route("test", "Host:test")), ), + frontend("rewritetargetrootpath/", + passHostHeader(), + routes( + route("/", "PathPrefix:/;ReplacePathRegex: ^(.*) /app$1"), + route("rewritetargetrootpath", "Host:rewritetargetrootpath")), + ), frontend("rewrite/api", passHostHeader(), routes( @@ -596,7 +608,7 @@ func TestProvider_loadIngresses(t *testing.T) { passHostHeader(), redirectRegex("root2/$", "root2/root2"), routes( - route("/", "PathPrefix:/;ReplacePathRegex: ^/(.*) /abc$1"), + route("/", "PathPrefix:/;ReplacePathRegex: ^(.*) /abc$1"), route("root2", "Host:root2"), ), ),