From d42e380e97f694a8c85833f0d995d9503e963fa6 Mon Sep 17 00:00:00 2001 From: Alex Rowley Date: Fri, 14 Jul 2017 20:59:02 +0100 Subject: [PATCH] Modify how locations are built The HTTPIngressPath defines the path as an extended POSIX regex. https://github.com/kubernetes/kubernetes/blob/master/pkg/apis/extensions/types.go#L704 This treats any path passed from the ingress as a regex based location block. The only exception to this is the / path, which is set as a prefix location block, this should work as a catchall without affecting other locations defined using regex location blocks. It should be noted that there may be some incompatibilities between the spec and the regex implementation within nginx. --- controllers/nginx/pkg/template/template.go | 23 ++++++++++++++----- .../nginx/pkg/template/template_test.go | 4 ++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/controllers/nginx/pkg/template/template.go b/controllers/nginx/pkg/template/template.go index 71dc52665..56fa9d2f3 100644 --- a/controllers/nginx/pkg/template/template.go +++ b/controllers/nginx/pkg/template/template.go @@ -185,8 +185,7 @@ func buildResolvers(a interface{}) string { return strings.Join(r, " ") } -// buildLocation produces the location string, if the ingress has redirects -// (specified through the ingress.kubernetes.io/rewrite-to annotation) +// Helper to create the correct path for location blocks func buildLocation(input interface{}) string { location, ok := input.(*ingress.Location) if !ok { @@ -194,10 +193,19 @@ func buildLocation(input interface{}) string { } path := location.Path + + // Although per spec all paths should be treated as regex + // returning slash directly will result in a fall through catchall + // prefix style location block instead which will match any path + // for which a regex is not defined + if path == slash { + return slash + } + + // When rewrite is enabled via the rewrite target annotation + // (ingress.kubernetes.io/rewrite-target) this allows the baseuri to be + // appended to the path if len(location.Redirect.Target) > 0 && location.Redirect.Target != path { - if path == slash { - return fmt.Sprintf("~* %s", path) - } // baseuri regex will parse basename from the given location baseuri := `(?.*)` if !strings.HasSuffix(path, slash) { @@ -207,7 +215,10 @@ func buildLocation(input interface{}) string { return fmt.Sprintf(`~* ^%s%s`, path, baseuri) } - return path + // Return an anchored regex location block, although not identical to the + // spec due to the type of regex used this is the closest nginx equivalent + // to the intended regex based path as defined in HTTPIngressPath + return fmt.Sprintf(`~* ^%s`, path) } func buildAuthLocation(input interface{}) string { diff --git a/controllers/nginx/pkg/template/template_test.go b/controllers/nginx/pkg/template/template_test.go index ac8a1b5c7..df9953556 100644 --- a/controllers/nginx/pkg/template/template_test.go +++ b/controllers/nginx/pkg/template/template_test.go @@ -42,7 +42,7 @@ var ( AddBaseURL bool }{ "invalid redirect / to /": {"/", "/", "/", "proxy_pass http://upstream-name;", false}, - "redirect / to /jenkins": {"/", "/jenkins", "~* /", + "redirect / to /jenkins": {"/", "/jenkins", "/", ` rewrite /(.*) /jenkins/$1 break; proxy_pass http://upstream-name; @@ -60,7 +60,7 @@ var ( rewrite /something-complex/(.*) /not-root/$1 break; proxy_pass http://upstream-name; `, false}, - "redirect / to /jenkins and rewrite": {"/", "/jenkins", "~* /", ` + "redirect / to /jenkins and rewrite": {"/", "/jenkins", "/", ` rewrite /(.*) /jenkins/$1 break; proxy_pass http://upstream-name; subs_filter '' '' r;