How to use nginx capture group to attach prefix to rewrite rule

4/11/2019

I am currently trying to rewrite four paths in kubernetes ingress.

The three are done but the static file path is a bit tricky.

My frontend path is /$1 -> /(.*) web-front-cluster-ip-service

I also need to rewrite all /img/$1 -> /img/(.*) apollo-api-cluster-ip-service

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: servers-ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  rules:
    - http:
        paths:
          - backend:
              serviceName: apollo-api-cluster-ip-service
              servicePort: 4000
            path: /apollo_api/?(.*)
          - backend:
              serviceName: rest-api-cluster-ip-service
              servicePort: 5000
            path: /rest/?(.*)
          - backend:
              serviceName: web-front-cluster-ip-service
              servicePort: 6000
            path: /?(.*)
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: statics-ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /img/$1
spec:
  rules:
    - http:
        paths:
        - backend:
            serviceName: apollo-api-cluster-ip-service
            servicePort: 4000
          path: /img/?$(.*)

My current setting looks like above but for unknown reason, I am not able to reach the route configured by the second route.

So what I am trying to do instead is to combine two routes together and provide prefix to capture group that matches /img

if I do

      - backend:
          serviceName: apollo-api-cluster-ip-service
          servicePort: 6000
        path: /?(.*)

it will route everything to apollo-api when I need any route that does not start with /img to be routed to web-front

so I need something like below

      - backend:
          serviceName: apollo-api-cluster-ip-service
          servicePort: 4000
        path: /img?(.*) <- somehow add /img to $(.*) because currently it rewrites `/img/static.png` -> `/static.png` but I need `/img/static.png` -> `/img/static.png`.

Any help would be appreciated.

-- forJ
kubernetes
kubernetes-ingress
nginx

1 Answer

8/20/2019

As mentioned in Rewrite Target documentation:

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

So I suppose your second ingress should look like:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: statics-ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /img/$2
spec:
  rules:
    - http:
        paths:
        - backend:
            serviceName: apollo-api-cluster-ip-service
            servicePort: 4000
          path: /img(/|$)(.*)

In this case $2 will reflect (.*)

-- VKR
Source: StackOverflow