<p>I have a few pods that I am trying to match URLs for their respective services.</p>
<p>Please note that I <strong>need to use</strong> <code>nginx.ingress.kubernetes.io/rewrite-target</code> to solve this and <strong>not</strong> <code>nginx.ingress.kubernetes.io/rewrite-target</code></p>
<p>My ingress config file looks like this. Notice the <code>/api/tile-server/</code> does not have any regex pattern</p>
<pre><code>apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-service
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: &quot;true&quot;
    nginx.ingress.kubernetes.io/force-ssl-redirect: &quot;true&quot;
    nginx.ingress.kubernetes.io/use-regex: &quot;true&quot;
    kubernetes.io/ingress.class: &quot;nginx&quot;
    cert-manager.io/cluster-issuer: &quot;letsencrypt-prod&quot;
  namespace: default
spec:
  tls:
    - hosts:
        - example.com
      secretName: tls-secret
  rules:
    - host: example.com
      http:
        paths:
          - path: /?(.*)
            backend:
              serviceName: client
              servicePort: 80
          - path: /api/auth/?(.*)
            backend:
              serviceName: auth
              servicePort: 8000
          - path: /api/data/?(.*)
            backend:
              serviceName: data
              servicePort: 8001
          - path: /api/tile-server/
            backend:
              serviceName: tile-server
              servicePort: 7800
</code></pre>
<ul>
<li><code>client</code> pod is a react app built inside nginx docker image working fine</li>
<li><code>nginx.conf</code> looks like this (if it's helpful)</li>
</ul>
<pre><code>server {
    # listen on port 80
    listen 80;
    # where the root here
    root /usr/share/nginx/html;
    # what file to server as index
    index index.html index.htm;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to redirecting to index.html
        try_files $uri $uri/ /index.html;
    }

    # Media: images, icons, video, audio, HTC
    location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
        expires 1M;
        access_log off;
        add_header Cache-Control &quot;public&quot;;
    }

    # Javascript and CSS files
    location ~* \.(?:css|js)$ {
        try_files $uri =404;
        expires 1y;
        access_log off;
        add_header Cache-Control &quot;public&quot;;
    }

    # Any route containing a file extension (e.g. /devicesfile.js)
    location ~ ^.+\..+$ {
        try_files $uri =404;
    }
}
</code></pre>
<ul>
<li><code>auth</code> and <code>data</code> are Flask API pods working fine</li>
<li><code>tile-server</code> is also a Flask pod but need not do any pattern matching. I need to match the exact <code>/api/tile-server/</code> URL</li>
</ul>
<p>I have tried the following patterns but failed:</p>
<ul>
<li><code>/api/tile-server/</code></li>
<li><code>/api/tile-server/?(.*)</code></li>
<li><code>/api/tile-server(/|$)?(.*)</code></li>
</ul>
<p>I can confirm that the pods/services are running on their proper ports and I am able to access them through node ports but not through load balancer/domain.
What would be the right pattern to exactly match <code>/api/tile-server/</code> URL?</p>

<p><strong>First solution</strong> - create separate ingress object for tile-server with rewrite-target annotation. This will work because ingress rules with the same host are merged together by ingress controller and separate ingress object allow for use of different annotations per object:</p>
<pre><code>apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: tile-ingress-service
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: &quot;true&quot;
    nginx.ingress.kubernetes.io/force-ssl-redirect: &quot;true&quot;
    nginx.ingress.kubernetes.io/rewrite-target: &quot;/$2&quot;
    kubernetes.io/ingress.class: &quot;nginx&quot;
    cert-manager.io/cluster-issuer: &quot;letsencrypt-prod&quot;
  namespace: default
spec:
  tls:
    - hosts:
        - example.com
      secretName: tls-secret
  rules:
    - host: example.com
      http:
        paths:
          - path: /api/tile-server(/|$)(.*)
            backend:
              serviceName: tile-server
              servicePort: 7800
</code></pre>
<p><strong>Second solution</strong> - rewrite current ingress to work with rewrite-path. Some regex changes are necessary.</p>
<p>Notice the non-capturing group notation: <code>(?:&lt;regex&gt;)</code>. This allows to skip numbering for these groups since I need everything relevant to be in the first group in order for it to work, because <code>rewrite-target: &quot;/$1&quot;</code>.</p>
<pre><code>apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-service
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: &quot;true&quot;
    nginx.ingress.kubernetes.io/force-ssl-redirect: &quot;true&quot;
    nginx.ingress.kubernetes.io/rewrite-target: &quot;/$1&quot;
    kubernetes.io/ingress.class: &quot;nginx&quot;
    cert-manager.io/cluster-issuer: &quot;letsencrypt-prod&quot;
  namespace: default
spec:
  tls:
    - hosts:
        - example.com
      secretName: tls-secret
  rules:
    - host: example.com
      http:
        paths:
          - path: /(.*)
            backend:
              serviceName: client
              servicePort: 80
          - path: /(api/auth(?:/|$).*)
            backend:
              serviceName: auth
              servicePort: 8000
          - path: /(api/data(?:/|$).*)
            backend:
              serviceName: data
              servicePort: 8001
          - path: /api/tile-server(?:/|$)(.*)
            backend:
              serviceName: tile-server
              servicePort: 7800
</code></pre>
<p>Here is how the rewrites will work for:</p>
<ul>
<li>auth service (same applies to data service)</li>
</ul>
<pre><code>    /api/auth      ---&gt;  /api/auth
    /api/auth/     ---&gt;  /api/auth/
    /api/auth/xxx  ---&gt;  /api/auth/xxx
</code></pre>
<ul>
<li>tile-server service:</li>
</ul>
<pre><code>    /api/tile-server      ---&gt;  /
    /api/tile-server/     ---&gt;  /
    /api/tile-server/xxx  ---&gt;  /xxx
</code></pre>
<ul>
<li>client service</li>
</ul>
<pre><code>    /xxx  ---&gt;  /xxx
</code></pre>
<p>Notice that the following paths will be forwarded to client service (where xxx is any alphanumerical string):</p>
<pre><code>    /api/authxxx
    /api/dataxxx
    /api/tile-serverxxx
</code></pre>
<p>If you want them to be forwaded to other/matching services, add <code>?</code> after <code>(?:/|$)</code> in path.</p>
