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.
This commit is contained in:
Alex Rowley 2017-07-14 20:59:02 +01:00
parent e6ca242563
commit d42e380e97
No known key found for this signature in database
GPG key ID: C0A11F24C7F74F35
2 changed files with 19 additions and 8 deletions

View file

@ -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 := `(?<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 {

View file

@ -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 '<head(.*)>' '<head$1><base href="$scheme://$http_host/$baseuri">' r;