0

I've an nginx configuration for about 40+ nodes server all written like:

location /39/api {
    proxy_pass http://172.31.32.233:3138;
}

location /io39 {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://172.31.32.233:3138;
}

location /40/api {
    proxy_pass http://172.31.32.233:3139;
}

location /io40 {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://172.31.32.233:3139;
}

As you can see the target node port increases with the ID into the /io39 and /39/api path, I know I can capture the number with a regexp into the location directive, but how can I increase the variable as an integer and use it as the destination port of the proxy, so I can write an unique directive for thousand ports ?

Thanks!

Leonardo Bernardini
  • 1,076
  • 13
  • 23

1 Answers1

1

Although there was an evaluation regex modifier in Perl and PHP prior to 5.5, as far as I know there is no any equivalent for nginx and no regex mathematics is possible. One of the possible techniques described in this answer. For example, you can add something like 30000 this way (I use the longest 4-digit regex pattern as first because regex matching locations are checked from first to last one):

location ~ "^/(\d{4})/api" {
    set $port 3$1;
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/io(\d{4})" {
    set $port 3$1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/(\d{3})/api" {
    set $port 30$1;
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/io(\d{3})" {
    set $port 30$1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/(\d{2})/api" {
    set $port 300$1;
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/io(\d{2})" {
    set $port 300$1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/(\d)/api" {
    set $port 3000$1;
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/io(\d)" {
    set $port 3000$1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://172.31.32.233:$port;
}

This will give you port number 30001 for /1/api or /io1 (as well as for /01/api or /io01), port number 30002 for /2/api or /io2 and so on up to 39999 for /9999/api or /io9999 URIs.

The other way is to use lua-nginx-module or OpenResty:

location ~ "^/(?<number>\d{1,4})/api" {
    set_by_lua_block $port { return ngx.var.number + 3099 }
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/io(?<number>\d{1,4})" {
    set_by_lua_block $port { return ngx.var.number + 3099 }
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://172.31.32.233:$port;
}
Ivan Shatsky
  • 13,267
  • 2
  • 21
  • 37