<p>Is it possible with the Nginx ingress controller for Kubernetes to have an ingress rule that routes to different services based on if a query string exists? For example..</p>
<p>/foo/bar -&gt; route to serviceA</p>
<p>/foo/bar?x=10 -&gt; route to serviceB</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - host: xxxx.com
    http:
      paths:
      - path: /foo/bar(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: serviceA
            port:
              number: 8001
      - path: /foo/bar(/|$)(.*)\?
        pathType: Prefix
        backend:
          service:
            name: serviceB
            port:
              number: 8002
</code></pre>

Michael Kobaly
<p>I managed to find a working solution for what you described with two ingress objects. With the example that you provided ingress won't be able to direct you towards <code>service-b</code> since nginx does not match query string at all. This is very well explained <a href="https://stackoverflow.com/questions/15713934/how-to-match-question-mark-as-regexp-on-nginx-conf-location">here</a>.</p>
<p>Ingress selects the proper backed based on path. So I have prepared separate path for the second backend and put a conditional redirect to it to the first path so when request reach the <code>/tmp</code> path it uses <code>service-b</code> backend and trims the tmp part from the request.</p>
<p>So here's the ingress that matches <code>/foo/bar</code> for the <code>backend-a</code></p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
            if ($args ~ .+){
                      rewrite ^ http://xxxx.com/foo/bar/tmp permanent;
                      }
spec:
  rules:
  - host: xxxx.com
    http:
      paths:
      - path: /foo/bar
        pathType: Prefix
        backend:
          serviceName: service-a
          servicePort: 80
</code></pre>
<p>And here is the ingress that matches <code>/foo/bar?</code> and whatever comes after for the <code>backend-b</code></p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress-rewrite
  annotations:
    nginx.ingress.kubernetes.io/use-regex: &quot;true&quot;
    nginx.ingress.kubernetes.io/rewrite-target: /foo/bar$1
spec:
  rules:
  - host: xxxx.com
    http:
      paths:
      - path: /foo/bar/tmp(.*)
        backend:
          serviceName: service-b
          servicePort: 80
</code></pre>
<p>Please note, that previous configuration leftovers can prevent that solution from working well. Clean up, redeploy and ingress controller restart should help in that situation.</p>
<p>Here are some tests to prove the case. First I have added the <code>xxxx.com</code> to <code>/etc/hosts</code>:</p>
<pre class="lang-sh prettyprint-override"><code>➜  ~ cat /etc/hosts
127.0.0.1       localhost
192.168.59.2 xxxx.com
</code></pre>
<p><strong>- Here we are testing the firs path <code>/foo/bar</code>:</strong></p>
<pre class="lang-sh prettyprint-override"><code>➜  ~ curl -L -v http://xxxx.com/foo/bar        
*   Trying 192.168.59.2...
* TCP_NODELAY set
* Connected to xxxx.com (192.168.59.2) port 80 (#0)
&gt; GET /foo/bar HTTP/1.1 &lt;----- See path here! 
&gt; Host: xxxx.com
&gt; User-Agent: curl/7.52.1
&gt; Accept: */*
&gt; 
&lt; HTTP/1.1 200 OK
&lt; Date: Tue, 13 Apr 2021 12:30:00 GMT
&lt; Content-Type: application/json; charset=utf-8
&lt; Content-Length: 644
&lt; Connection: keep-alive
&lt; X-Powered-By: Express
&lt; ETag: W/&quot;284-P+J4oZl3lklvyqdp6FEGTPVw/VM&quot;
&lt; 
{
  &quot;path&quot;: &quot;/foo/bar&quot;,
  &quot;headers&quot;: {
    &quot;host&quot;: &quot;xxxx.com&quot;,
    &quot;x-request-id&quot;: &quot;1f7890a47ca1b27d2dfccff912d5d23d&quot;,
    &quot;x-real-ip&quot;: &quot;192.168.59.1&quot;,
    &quot;x-forwarded-for&quot;: &quot;192.168.59.1&quot;,
    &quot;x-forwarded-host&quot;: &quot;xxxx.com&quot;,
    &quot;x-forwarded-port&quot;: &quot;80&quot;,
    &quot;x-forwarded-proto&quot;: &quot;http&quot;,
    &quot;x-scheme&quot;: &quot;http&quot;,
    &quot;user-agent&quot;: &quot;curl/7.52.1&quot;,
    &quot;accept&quot;: &quot;*/*&quot;
  },
  &quot;method&quot;: &quot;GET&quot;,
  &quot;body&quot;: &quot;&quot;,
  &quot;fresh&quot;: false,
  &quot;hostname&quot;: &quot;xxxx.com&quot;,
  &quot;ip&quot;: &quot;192.168.59.1&quot;,
  &quot;ips&quot;: [
    &quot;192.168.59.1&quot;
  ],
  &quot;protocol&quot;: &quot;http&quot;,
  &quot;query&quot;: {},
  &quot;subdomains&quot;: [],
  &quot;xhr&quot;: false,
  &quot;os&quot;: {
    &quot;hostname&quot;: &quot;service-a&quot; &lt;------ Pod hostname that response came from.
</code></pre>
<p><strong>- And here we are testing the firs path <code>/foo/bar</code>:</strong></p>
<pre class="lang-yaml prettyprint-override"><code>➜  ~ curl -L -v http://xxxx.com/foo/bar\?x\=10 
*   Trying 192.168.59.2...
* TCP_NODELAY set
* Connected to xxxx.com (192.168.59.2) port 80 (#0)
&gt; GET /foo/bar?x=10 HTTP/1.1 &lt;--------- The requested path! 
&gt; Host: xxxx.com
&gt; User-Agent: curl/7.52.1
&gt; Accept: */*
&gt; 
&lt; HTTP/1.1 301 Moved Permanently
&lt; Date: Tue, 13 Apr 2021 12:31:58 GMT
&lt; Content-Type: text/html
&lt; Content-Length: 162
&lt; Connection: keep-alive
&lt; Location: http://xxxx.com/foo/bar/tmp?x=10
&lt; 
* Ignoring the response-body
* Curl_http_done: called premature == 0
* Connection #0 to host xxxx.com left intact
* Issue another request to this URL: 'http://xxxx.com/foo/bar/tmp?x=10'
* Found bundle for host xxxx.com: 0x55d6673218a0 [can pipeline]
* Re-using existing connection! (#0) with host xxxx.com
* Connected to xxxx.com (192.168.59.2) port 80 (#0)
&gt; GET /foo/bar/tmp?x=10 HTTP/1.1
&gt; Host: xxxx.com
&gt; User-Agent: curl/7.52.1
&gt; Accept: */*
&gt;  
{
  &quot;path&quot;: &quot;/foo/bar&quot;,
  &quot;headers&quot;: {
    &quot;host&quot;: &quot;xxxx.com&quot;,
    &quot;x-request-id&quot;: &quot;96a949a407dae653f739db01fefce7bf&quot;,
    &quot;x-real-ip&quot;: &quot;192.168.59.1&quot;,
    &quot;x-forwarded-for&quot;: &quot;192.168.59.1&quot;,
    &quot;x-forwarded-host&quot;: &quot;xxxx.com&quot;,
    &quot;x-forwarded-port&quot;: &quot;80&quot;,
    &quot;x-forwarded-proto&quot;: &quot;http&quot;,
    &quot;x-scheme&quot;: &quot;http&quot;,
    &quot;user-agent&quot;: &quot;curl/7.52.1&quot;,
    &quot;accept&quot;: &quot;*/*&quot;
  },
  &quot;method&quot;: &quot;GET&quot;,
  &quot;body&quot;: &quot;&quot;,
  &quot;fresh&quot;: false,
  &quot;hostname&quot;: &quot;xxxx.com&quot;,
  &quot;ip&quot;: &quot;192.168.59.1&quot;,
  &quot;ips&quot;: [
    &quot;192.168.59.1&quot;
  ],
  &quot;protocol&quot;: &quot;http&quot;,
  &quot;query&quot;: {
    &quot;x&quot;: &quot;10&quot;
  },
  &quot;subdomains&quot;: [],
  &quot;xhr&quot;: false,
  &quot;os&quot;: {
    &quot;hostname&quot;: &quot;service-b&quot; &lt;-----Service-b host name!
  },
  &quot;connection&quot;: {}
</code></pre>
<p>For the responses I've used the  <code>mendhak/http-https-echo</code> image:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: Pod
metadata:
  name: service-b
  labels:
    app: echo2
spec:
  containers:
  - name: service-b #&lt;-------- service-b host name
    image: mendhak/http-https-echo
    ports:
    - containerPort: 80
</code></pre>
