https://github.com/kubernetes/kubernetes/blob/master/pkg/apis/extensions/v1beta1/types.go#L690:
Path is an extended POSIX regex as defined by IEEE Std 1003.1, (i.e this follows the egrep/unix syntax, not the perl syntax) matched against the path of an incoming request. Currently it can contain characters disallowed from the conventional "path" part of a URL as defined by RFC 3986. Paths must begin with a '/'.
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: re-path-ingress
spec:
rules:
- host: "echo.example.com"
http:
paths:
- path: "/.*/foo"
backend:
serviceName: echoserver
servicePort: http
This by itself does not work, and instead creates an ingress for literally '/.*/foo'. Adding a rewrite-target however makes things magically behave differently:
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: re-path-ingress
annotations:
ingress.kubernetes.io/rewrite-target: "/"
spec:
rules:
- host: "echo.example.com"
http:
paths:
- path: "/.*/foo"
backend:
serviceName: echoserver
servicePort: http
This is in my eyes very surprising, and I could not find any documentation describing this behavior. If this is an intentional limitation of the nginx ingress controller (tested with 0.9.0-beta.3), then it should be minimally documented somewhere.
FWIW: Source is buildLocation: only when there is a rewrite-target will it produce a regex location.
This is a follow-up/fold-out from #565.
Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.
Prevent issues from auto-closing with an /lifecycle frozen comment.
If this issue is safe to close now please do so with /close.
Send feedback to sig-testing, kubernetes/test-infra and/or @fejta.
/lifecycle stale
Stale issues rot after 30d of inactivity.
Mark the issue as fresh with /remove-lifecycle rotten.
Rotten issues close after an additional 30d of inactivity.
If this issue is safe to close now please do so with /close.
Send feedback to sig-testing, kubernetes/test-infra and/or @fejta.
/lifecycle rotten
/remove-lifecycle stale
Rotten issues close after 30d of inactivity.
Reopen the issue with /reopen.
Mark the issue as fresh with /remove-lifecycle rotten.
Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/close
Can this be reopened? Without something like an annotation to set what type of match the location should use that is not just a prefix match, the rewrite-target annotation needs to be used. However, using the rewrite-target has some other specific properties of its own. For instance, if I wanted locations like the following:
location ~* ^/a/app2/api {
...
}
location ~* ^/a/app1/api {
...
}
location ~* ^/a($|/) {
...
}
location / {
...
}
so that paths like the following would all go to different services: /a/app/api/blah, /a/app2/api/blah, /a/settings, and /apps, some workarounds need to be done.
The first problem is that you cannot set a rewrite-target and a path that match and still get a regex match because when the location is built, this is checked:
https://github.com/kubernetes/ingress-nginx/blob/d744c2eba78e084801907bb79af694defa7c487d/internal/ingress/controller/template/template.go#L201
So just doing the following will not work:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /a/app/api
name: rewrite
namespace: default
spec:
rules:
- host: rewrite.bar.com
http:
paths:
- backend:
serviceName: echoheaders
servicePort: 80
path: /a/app/api
They need to be different, which you can get around by changing the path to:
path: /a/app/api/?
This results in a location like
location ~* ^/a/app/api/?\/?(?<baseuri>.*)
and a rewrite rule like
rewrite /a/app/api/?/(.*) /a/app/api/$1 break;
which works for the longer matches, but is a useless rewrite rule.
For matching on the /a, we would want a path like
path: /a($|/)
so that we do not match on things like /apps. But since there is no way to just specify a regex match for a location, a rewrite-target needs defined (in this case just /a) which results in the extra regex added on to the location match, as well as the following useless rewrite rule
rewrite /a($|/)/(.*) /a/$1 break;
because it does not even match against the path (the double /s).
Having just an annotation like nginx.ingress.kubernetes.io/location-regex-match: true or something would be much more clear (and better optimized since there is no rewrite rule created) instead of defining the same path as the rule. Even just allowing the rewrite-target and the path to match would be better, and I cannot think of a reason why it may be bad to not allow it.
Most helpful comment
Can this be reopened? Without something like an annotation to set what type of match the
locationshould use that is not just a prefix match, therewrite-targetannotation needs to be used. However, using therewrite-targethas some other specific properties of its own. For instance, if I wantedlocations like the following:so that paths like the following would all go to different services:
/a/app/api/blah,/a/app2/api/blah,/a/settings, and/apps, some workarounds need to be done.The first problem is that you cannot set a
rewrite-targetand a path that match and still get a regex match because when thelocationis built, this is checked:https://github.com/kubernetes/ingress-nginx/blob/d744c2eba78e084801907bb79af694defa7c487d/internal/ingress/controller/template/template.go#L201
So just doing the following will not work:
They need to be different, which you can get around by changing the
pathto:This results in a
locationlikeand a rewrite rule like
which works for the longer matches, but is a useless rewrite rule.
For matching on the
/a, we would want a path likeso that we do not match on things like
/apps. But since there is no way to just specify a regex match for alocation, arewrite-targetneeds defined (in this case just/a) which results in the extra regex added on to thelocationmatch, as well as the following useless rewrite rulebecause it does not even match against the path (the double
/s).Having just an annotation like
nginx.ingress.kubernetes.io/location-regex-match: trueor something would be much more clear (and better optimized since there is no rewrite rule created) instead of defining the same path as the rule. Even just allowing therewrite-targetand thepathto match would be better, and I cannot think of a reason why it may be bad to not allow it.