带有正则表达式的 Nginx 变量

时间:2021-05-21 17:19:23

标签: nginx configuration

我有一个大约 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;
}

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

谢谢!

1 个答案:

答案 0 :(得分:1)

虽然在 5.5 之前的 Perl 和 PHP 中有一个 evaluation 正则表达式修饰符,但据我所知,nginx 没有任何等价物,也没有正则表达式数学是可能的。 this 答案中描述的可能技术之一。例如,您可以通过这种方式添加类似 30000 的内容(我使用最长的 4 位正则表达式模式作为第一个,因为从第一个到最后一个检查正则表达式匹配位置):

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

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

另一种方法是使用 lua-nginx-moduleOpenResty

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