带有正则表达式的 Nginx 变量

Nginx variable with regexp

我有一个用于大约 40 多个节点服务器的 nginx 配置,全部写成:

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;
}

如您所见,目标节点端口随着 /io39 和 /39/api 路径中的 ID 增加,我知道我可以使用正则表达式将数字捕获到位置指令中,但如何才能我将变量增加为一个整数并将其用作代理的目标端口,因此我可以为千个端口编写一个唯一的指令?

谢谢!

尽管有一个 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 答案。例如,您可以通过这种方式添加类似 30000 的内容(我首先使用最长的 4 位正则表达式模式,因为正则表达式匹配位置是从第一个到最后一个检查的):

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

location ~ "^/io(\d{4})" {
    set $port 3;
    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;
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/io(\d{3})" {
    set $port 30;
    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;
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/io(\d{2})" {
    set $port 300;
    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;
    proxy_pass http://172.31.32.233:$port;
}

location ~ "^/io(\d)" {
    set $port 3000;
    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;
}

这将为您提供 /1/api/io1(以及 /01/api/io01)的端口号 30001,[=17= 的端口号 30002 ] 或 /io2 等等 /9999/api/io9999 URI 最多 39999。

另一种方法是使用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;
}