Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Route path to different backends depending on http method (GET vs POST) #187

Closed
gjcarneiro opened this issue Jan 29, 2017 · 11 comments
Closed

Comments

@gjcarneiro
Copy link

Hi, I would like to route the same URL to different backends depending on the HTTP method:

  1. GET /v1/orders/ would go to one backend (since it is a DB query, potentially slow);
  2. POST /v1/orders/ would go to another backend.

As far as I can tell, this is not supported. Any plans to support this scenario?

@pieterlange
Copy link
Contributor

pieterlange commented Jan 30, 2017

I don't think this is in scope for the ingress controller. It sounds like you're looking for something like apigee.

https://apigee.com/about/blog/digital-business/api-management-kubernetes

@aledbf
Copy link
Member

aledbf commented Mar 8, 2017

@gjcarneiro this is possible but it will make the use or debugging more complex than it should be.

@aledbf
Copy link
Member

aledbf commented Jun 16, 2017

Closing. This is out of the scope of the ingress controller. Please reopen if you have more questions

@aledbf aledbf closed this as completed Jun 16, 2017
@mattwilliamson
Copy link

I believe it is in scope. If ingress-nginx is not supposed to route traffic to different backends depending on the traffic coming in, what is the scope it is meant to address?

@aledbf
Copy link
Member

aledbf commented Jan 29, 2019

I believe it is in scope

I am sorry but the Ingress spec does not support this.

@gjcarneiro
Copy link
Author

It could be supported by an annotation, perhaps? I am happy to create a separate Ingress just for this.

@smirzai
Copy link

smirzai commented Feb 20, 2019

I also think that is a useful feature to have. Http verb is part of http address just like a verb. Is there a voting mechanism we can know how many others have the same idea?
Will a pull request implementing it will be considered?

@ElvinEfendi
Copy link
Member

ingress-nginx now has internals implemented to support multi-backend per path. Canary feature is just one feature that is built on top of it.

As a starter we can piggyback on canary and introduce another set annotations such as

alternative-backend-by-http-method: "*|POST|GET|etc."

So in the example given you would have a normal ingress defining /v1/orders/ without any extra stuff
and another ingress where canary annotation is set to true and alternative-backend-by-http-method annotation is set to POST. This would make sure POST requests on that endpoint gets proxied to the backend service configured in the second ingress where canary is enabled.

Even though we currently support only two backends, we have the foundation built to support many:

-- TODO: support traffic shaping for n > 1 alternative backends

We will also eventually have to come up with better annotation names.

@christhomas
Copy link

This is absolutely in scope for an ingress controller. I can't see how this is not an obvious thing to support. It's an underpinning functionality of EVERY. SINGLE. REST. API. EVER. How could you not want to support it?

If the spec doesn't include this, then update the spec. Don't downgrade expectations

@vaslabs
Copy link

vaslabs commented Jan 21, 2020

I found a way that works for me, posting it here for reference, if you are using this controller. Use at your own risk :)

  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/configuration-snippet: |
      internal;
      rewrite ^ $original_uri break;
    nginx.ingress.kubernetes.io/server-snippet: |
      location /api/does/not/matter/much {
        if ( $request_method = GET) {
          set $target_destination '/_read';
        }
        if ( $request_method != GET) {
          set $target_destination '/_write';
        }
        set $original_uri $uri;
        rewrite ^ $target_destination last;
      }

And on the paths

paths:
          - path: /_read
            backend:
              serviceName: read-service
              servicePort: 8080
          - path: /_write
            backend:
              serviceName: write-service
              servicePort: 8080

This was inspired from the linked ticket on nginxinc and I tested it on a test environment. Haven't observed any weird side effects yet

@VGerris
Copy link

VGerris commented Apr 27, 2021

thanks @vaslabs for the snippet. Any way to support regex in the location? I tried it but it does not seem to match, the services are associated though.
so I would like :
GET /api/v([0-9]+)/test
POST/api/v([0-9]+)/test
When I use that in the location, it does not seem to work.
Any solution is appreciated. Thanks for the linked CQRS ticket too, I made a comment.
Seems very useful to have HTTP verb based simple addition to a path match.
thanks!

[update] it does not seem to work with a non-regular expression either. A more complete example would be greatly appreciated.
[update2]

Got it to work by writing location like:
location ~* "^/api/v1/test"
seems to work with regex too.
Credit : https://stackoverflow.com/questions/63275239/kubernetes-nginx-ingress-server-snippet-annotation-not-taking-effect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants