<p>I have nginx ingress installed on my cluster. Here is the yaml</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-client
  annotations:
    kubernetes.io/ingress.class: nginx
  namespace: dev
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: client-service
            port: 
              number: 80
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port: 
              number: 80
</code></pre>
<p>When I hit / prefix it is good.
curl <a href="http://example.com" rel="nofollow noreferrer">http://example.com</a> (All Good)</p>
<p>Problem:</p>
<p>But when I hit / api prefix, it returns /api of the service not / of the service</p>
<p>curl <a href="http://example.com/api" rel="nofollow noreferrer">http://example.com/api</a> (It <strong>should link to api-service</strong>, but it is linking to api-service/api)</p>
<p>Any help will be appreciated!</p>

<p>This is because a path <code>/</code> with type <code>Prefix</code> will match <code>/</code> and everything after, including <code>/api</code>. So your first rule overshadows the second rule in some sense.</p>
<hr />
<p>I don't know if it's an option for you, but it would be probably most elegant and idiomatic to use different hostnames for both services. If you deploy <a href="https://cert-manager.io/docs/" rel="nofollow noreferrer">cert-manager</a>, this shouldn't be a problem.</p>
<pre class="lang-yaml prettyprint-override"><code>rules:
- host: example.com
  http:
    paths:
    - path: /
      pathType: Prefix
      backend:
        service:
          name: client-service
          port: 
            number: 80
# use a different hostname for the api
- host: api.example.com
  http:
    paths:
    - path: /
      pathType: Prefix
      backend:
        service:
          name: api-service
          port: 
            number: 80
</code></pre>
<hr />
<p>Another option could be to use <a href="https://kubernetes.github.io/ingress-nginx/user-guide/ingress-path-matching/" rel="nofollow noreferrer">regex</a> in your frontend path rule. And let it not match when the slash is followed by api. For that, you need to set an annotation.</p>
<pre class="lang-yaml prettyprint-override"><code>annotations:
  nginx.ingress.kubernetes.io/use-regex: &quot;true&quot;
</code></pre>
<p>Then you can do something like the below for your frontend service. Using a <a href="https://www.regextutorial.org/positive-and-negative-lookahead-assertions.php" rel="nofollow noreferrer">negative lookahead</a>.</p>
<pre><code>- path: /(?!api).*
</code></pre>
<hr />
<p>Alternatively, but less pretty, you could add a path prefix to your frontend service and strip it away via <a href="https://kubernetes.github.io/ingress-nginx/examples/rewrite/" rel="nofollow noreferrer">path rewrite</a> annotation. But then you may have to write two separate ingress manifests as this is annotation counts for both, or you need to use a more complex path rewrite rule.</p>
<pre class="lang-yaml prettyprint-override"><code>annotations:
  nginx.ingress.kubernetes.io/rewrite-target: /$2
</code></pre>
<pre class="lang-yaml prettyprint-override"><code>- path: /ui(/|$)(.*)
</code></pre>
<hr />
<p>Perhaps it's also sufficient to move the more specific route, <code>/api</code>, before the generic <code>/</code> route. In that case, switch the path around in the list. If they end up in that order in the nginx config, nginx should be able to handle it as desired.</p>
