How to configure nginx.ingress.kubernetes.io/rewrite-target and spec.rules.http.paths.path to satisfy the following URI patterns

5/23/2019

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:

  • a = Any letter between a-z. Lowercase. Exactly 2 letters - no more, no less.
  • b = Any letter between a-z. Lowercase. Exactly 2 letters - no more, no less.
  • c = any valid URI character. Lowercase. Of variable length - think slug.

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:

  1. https://kubernetes.github.io/ingress-nginx/examples/rewrite/
  2. https://github.com/kubernetes/ingress-nginx/pull/3174
-- PussInBoots
kubernetes
kubernetes-ingress
nginx
nginx-ingress
regex

2 Answers

5/28/2019

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 aas 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.

-- Gilgames
Source: StackOverflow

5/29/2019

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
-- PussInBoots
Source: StackOverflow