Nginx 位置语句在正则表达式和正常匹配中的行为不同
Nginx location statement behaves differently in regex and normal matching
我在这两种情况下看到了不同的行为:
location ~ /(?<version>v[12]) {
proxy_pass https://localhost/api/$version;
}
location /v2 {
proxy_pass https://localhost/api/v2;
}
如果我请求 /v2/login
,我会在正则表达式配置中看到对 /v2
的请求,而直接匹配会正确保留整个请求 url.
我尝试添加第二个捕获组,/(?<version>v[12])/(?<path>.*)
,然后它基本上起作用了。但是,它似乎与 PUT/POST 混为一谈。
我是否缺少一些解释?我阅读了 documentation,但据我所知,使用或不使用正则表达式应该没有任何区别。
不幸的是,官方文档缺少许多重要说明。如果您发现 Nginx 有一些文档无法解释的异常情况,那么我建议您查看 wiki。在你的情况下,有趣的部分是:
A special case is using variables in the proxy_pass statement: The
requested URL is not used and you are fully responsible to construct
the target URL yourself.
因此,一旦您在 proxy_pass
指令中引入 $version
,Nginx 便开始忽略原始请求 URI,仅发送 proxy_pass
URI 部分中的内容。
这就是为什么如果你只需要涵盖两种情况(v1
和 v2
),我强烈建议不要乱用正则表达式,而是像你一样定义两个公共前缀位置在你的第二个例子中做了。 Nginx配置不是编程代码,重复部分配置就可以了。
但是,如果出于某种原因您确实必须使用正则表达式位置,则您将不得不重写您的 URI:
location ~ /(?<version>v[12]) {
rewrite ^/(.*)$ /api/ break;
proxy_pass https://localhost;
}
或者自己构造完整的URI:
location ~ /(?<version>v[12])(?<rest>.*)$ {
proxy_pass https://localhost/api/$version$rest$is_args$args;
}
我在这两种情况下看到了不同的行为:
location ~ /(?<version>v[12]) {
proxy_pass https://localhost/api/$version;
}
location /v2 {
proxy_pass https://localhost/api/v2;
}
如果我请求 /v2/login
,我会在正则表达式配置中看到对 /v2
的请求,而直接匹配会正确保留整个请求 url.
我尝试添加第二个捕获组,/(?<version>v[12])/(?<path>.*)
,然后它基本上起作用了。但是,它似乎与 PUT/POST 混为一谈。
我是否缺少一些解释?我阅读了 documentation,但据我所知,使用或不使用正则表达式应该没有任何区别。
不幸的是,官方文档缺少许多重要说明。如果您发现 Nginx 有一些文档无法解释的异常情况,那么我建议您查看 wiki。在你的情况下,有趣的部分是:
A special case is using variables in the proxy_pass statement: The requested URL is not used and you are fully responsible to construct the target URL yourself.
因此,一旦您在 proxy_pass
指令中引入 $version
,Nginx 便开始忽略原始请求 URI,仅发送 proxy_pass
URI 部分中的内容。
这就是为什么如果你只需要涵盖两种情况(v1
和 v2
),我强烈建议不要乱用正则表达式,而是像你一样定义两个公共前缀位置在你的第二个例子中做了。 Nginx配置不是编程代码,重复部分配置就可以了。
但是,如果出于某种原因您确实必须使用正则表达式位置,则您将不得不重写您的 URI:
location ~ /(?<version>v[12]) {
rewrite ^/(.*)$ /api/ break;
proxy_pass https://localhost;
}
或者自己构造完整的URI:
location ~ /(?<version>v[12])(?<rest>.*)$ {
proxy_pass https://localhost/api/$version$rest$is_args$args;
}