3

I am currently writing a dispatcher that will dispatch different URLs to specific service URLS.

I essentially want to dispatch something like:

POST http://nginx/awesome_service/a/lot/of/params/and?so=on

to

POST http://awesome_service/a/lot/of/params/and?so=on

I already achieved by hard coding the service name:

location /awesome_service {
    rewrite ^/awesome_service(/.*)$ $1 break;
    proxy_pass http://awesome_service;
}

However I have different services with different names and I don't want to duplicate the routes.

I used a map to from name to url:

map $uri $service_url {
  ~^/awesome_service/ "http://awesome_service";
  ~^/mediocre_service/ "http://mediocre_service";
}

So it's easy to dispatch to a variable proxy url:

location /awesome_service {
    rewrite ^/awesome_service(/.*)$ $1 break;
    proxy_pass $service_url;
}

However, I'm still struggling with the rewriting.

This is what I came up with so far:

location ~ ^/([^\/]+)/.* {
    set $service $1;
    rewrite ^/$service(/.*)$ $1 break;
    proxy_pass $service_url;
}

The request is captured and passed on. But the rewriting fails. The service still sees the first part of the url.

Is there maybe a mixup with the regex or am I passing in the variable wrong?

1
  • Do you have tens or hundreds of applications? If not it's better stick with several explicit location blocks.
    – Alexey Ten
    Jun 4 '14 at 19:46
1

The rewrite in your location block gets evaluated first, then proxy_pass is used. This is the reason your map block won't work with $uri. Because when the map block is triggered the URL is already rewritten. I have this config in my lab which works as expected:

map $custom_service $custom_backend {
        google "https://www.google.com";
        bing "https://www.bing.com";
}
location ~ ^/([^\/]+)/.* {
        set $custom_service $1;
        rewrite ^/[^\/]+(/.*)$ $1 break;
        proxy_pass $custom_backend;
}

The map block goes into the http block and the location block into the server block.

Your URLs look like this:

http://nginx/google/some/params -> backend is now -> https://www.google.com/some/params
http://nginx/bing/some/params -> backend is now -> https://www.bing.com/some/params

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.