diff --git a/docs/configuration/backends/kubernetes.md b/docs/configuration/backends/kubernetes.md index e11ca7325..bc0a68a19 100644 --- a/docs/configuration/backends/kubernetes.md +++ b/docs/configuration/backends/kubernetes.md @@ -205,8 +205,9 @@ retryexpression: IsNetworkError() && Attempts() <= 2 <4> `traefik.ingress.kubernetes.io/app-root`: Non-root paths will not be affected by this annotation and handled normally. -This annotation may not be combined with the `ReplacePath` rule type or any other annotation leveraging that rule type. -Trying to do so leads to an error and the corresponding Ingress object being ignored. +This annotation may not be combined with other redirect annotations. +Trying to do so will result in the other redirects being ignored. +This annotation can be used in combination with `traefik.ingress.kubernetes.io/redirect-permanent` to configure whether the `app-root` redirect is a 301 or a 302. <5> `traefik.ingress.kubernetes.io/service-weights`: Service weights enable to split traffic across multiple backing services in a fine-grained manner. diff --git a/provider/kubernetes/kubernetes.go b/provider/kubernetes/kubernetes.go index c89e244f4..085131488 100644 --- a/provider/kubernetes/kubernetes.go +++ b/provider/kubernetes/kubernetes.go @@ -258,7 +258,7 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error) Routes: make(map[string]types.Route), Priority: priority, WhiteList: getWhiteList(i), - Redirect: getFrontendRedirect(i), + Redirect: getFrontendRedirect(i, baseName, pa.Path), EntryPoints: entryPoints, Headers: getHeader(i), Errors: getErrorPages(i), @@ -500,7 +500,7 @@ func (p *Provider) addGlobalBackend(cl Client, i *extensionsv1beta1.Ingress, tem Routes: make(map[string]types.Route), Priority: priority, WhiteList: getWhiteList(i), - Redirect: getFrontendRedirect(i), + Redirect: getFrontendRedirect(i, defaultFrontendName, "/"), EntryPoints: entryPoints, Headers: getHeader(i), Errors: getErrorPages(i), @@ -531,25 +531,12 @@ func getRuleForPath(pa extensionsv1beta1.HTTPIngressPath, i *extensionsv1beta1.I rules := []string{ruleType + ":" + pa.Path} - var pathReplaceAnnotation string - if ruleType == ruleTypeReplacePath { - pathReplaceAnnotation = annotationKubernetesRuleType - } - if rewriteTarget := getStringValue(i.Annotations, annotationKubernetesRewriteTarget, ""); rewriteTarget != "" { - if pathReplaceAnnotation != "" { - return "", fmt.Errorf("rewrite-target must not be used together with annotation %q", pathReplaceAnnotation) + if ruleType == ruleTypeReplacePath { + 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, "/")) rules = append(rules, rewriteTargetRule) - pathReplaceAnnotation = annotationKubernetesRewriteTarget - } - - if rootPath := getStringValue(i.Annotations, annotationKubernetesAppRoot, ""); rootPath != "" && pa.Path == "/" { - if pathReplaceAnnotation != "" { - return "", fmt.Errorf("app-root must not be used together with annotation %q", pathReplaceAnnotation) - } - rules = append(rules, ruleTypeReplacePath+":"+rootPath) } if requestModifier := getStringValue(i.Annotations, annotationKubernetesRequestModifier, ""); requestModifier != "" { @@ -859,9 +846,17 @@ func loadAuthTLSSecret(namespace, secretName string, k8sClient Client) (string, return getCertificateBlocks(secret, namespace, secretName) } -func getFrontendRedirect(i *extensionsv1beta1.Ingress) *types.Redirect { +func getFrontendRedirect(i *extensionsv1beta1.Ingress, baseName, path string) *types.Redirect { permanent := getBoolValue(i.Annotations, annotationKubernetesRedirectPermanent, false) + if appRoot := getStringValue(i.Annotations, annotationKubernetesAppRoot, ""); appRoot != "" && path == "/" { + return &types.Redirect{ + Regex: fmt.Sprintf("%s$", baseName), + Replacement: fmt.Sprintf("%s/%s", strings.TrimRight(baseName, "/"), strings.TrimLeft(appRoot, "/")), + Permanent: permanent, + } + } + redirectEntryPoint := getStringValue(i.Annotations, annotationKubernetesRedirectEntryPoint, "") if len(redirectEntryPoint) > 0 { return &types.Redirect{ diff --git a/provider/kubernetes/kubernetes_test.go b/provider/kubernetes/kubernetes_test.go index 576d00aad..2f473d91e 100644 --- a/provider/kubernetes/kubernetes_test.go +++ b/provider/kubernetes/kubernetes_test.go @@ -1470,8 +1470,9 @@ rateset: ), frontend("root/", passHostHeader(), + redirectRegex("root/$", "root/root"), routes( - route("/", "PathPrefix:/;ReplacePath:/root"), + route("/", "PathPrefix:/"), route("root", "Host:root"), ), ),