How can I configure nginx.ingress.kubernetes.io/rewrite-target
and spec.rules.http.paths.path
to satisfy the following URI patterns?
/aa/bb-aa/coolapp
/aa/bb-aa/coolapp/cc
Legend:
Example URI:s that should match the above pattern:
/us/en-us/coolapp
/us/en-us/coolapp/faq
/us/en-us/coolapp/privacy-policy
Attention
Starting in Version 0.22.0, ingress definitions using the annotation nginx.ingress.kubernetes.io/rewrite-target
are not backwards compatible with previous versions. In Version 0.22.0 and beyond, any substrings within the request URI that need to be passed to the rewritten path must explicitly be defined in a capture group.
Note
Captured groups are saved in numbered placeholders, chronologically, in the form $1
, $2
... $n
. These placeholders can be used as parameters in the rewrite-target annotation.
References:
The nginx.ingress.kubernetes.io/rewrite-target
annotation is used to indicate the target URI where the traffic must be redirected. As per how I understand your question, you only want to match the URI patterns that you specified without redirecting the traffic. In order to achieve this, you can set the nginx.ingress.kubernetes.io/use-regex
annotation to true
, thus enabling regular expressions in the spec.rules.http.paths.path
field.
Let's now take a look at the regex that you will need to match your URI patterns. First of all, the regex engine used by ingress-nginx doesn't support backreferences, therefore a regex like this one will not work. This is not a problem as you can match the /aa-bb/aa
part without forcing the two aa
s to be equal since you will —presumably— still have to check the correctness of the URI later on in your service (e.g /us/en-us
may be accepted whereas /ab/cd-ab
may not).
You can use this regex to match the specified URI patterns:
/[a-z]{2}/[a-z]{2}-[a-z]{2}/coolapp(/.*)?
If you want to only match URL slugs in the cc
part of the pattern you specified, you can use this regex instead:
/[a-z]{2}/[a-z]{2}-[a-z]{2}/coolapp(/[a-z0-9]+([a-z0-9]+)*)?
Lastly, as the nginx.ingress.kubernetes.io/use-regex
enforces case insensitive regex, using [A-Z]
instead of [a-z]
would lead to the same result.
Follows an ingress example definition using the use-regex
annotation:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-regex
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: test.com
http:
paths:
- path: /[a-z]{2}/[a-z]{2}-[a-z]{2}/coolapp(/.*)?
backend:
serviceName: test
servicePort: 80
You can find more information about Ingress Path Matching in the official user guide.
Came up with the following configuration - it is working for all of my test routes / requirements so far.
The regex is almost the same as the one posted by @Gilgames.
I based mine on the official docs rewrite example: https://kubernetes.github.io/ingress-nginx/examples/rewrite/#rewrite-target
Apart from that I took a quick course at https://www.regular-expressions.info/
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ing
namespace: some-ns
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1/$2-$3/$5
certmanager.k8s.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "INGRESSCOOKIE"
nginx.ingress.kubernetes.io/session-cookie-path: /
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($host = 'example.com')
{
rewrite ^ https://www.example.com$request_uri permanent;
}
spec:
tls:
- hosts:
- www.example.com
- example.com
secretName: tls-secret-test
rules:
- host: www.example.com
http:
paths:
- path: /([a-z]{2})/([a-z]{2})-([a-z]{2})/coolapp(/|$)(.*)
backend:
serviceName: coolapp-svc
servicePort: 80
- host: example.com
http:
paths:
- path: /([a-z]{2})/([a-z]{2})-([a-z]{2})/coolapp(/|$)(.*)
backend:
serviceName: coolapp-svc
servicePort: 80