Nginx重写与正则表达式多个令牌(+)

时间:2016-12-11 06:59:54

标签: nginx nginx-location

当遇到多个令牌号时,我遇到了一些重写问题。

我正在开发版本的API,因此不推荐的版本调用将转到我们的最新版本。为简单起见,我们假设我们支持v4v5。当某些人点击v1-3时,我们需要转到v5。同样,如果有人点击v6,也应该转到v5

我们的nginx.conf使用带有上游的proxy_pass,所以我让每个版本在不同的端口上运行

upstream v4 {
  server 127.0.0.1:3000
}

upstream v5 {
  server 127.0.0.1:3001
}

然后我们使用位置块代理

location ^~ /v5 {
  proxy_pass $scheme://v5;
}

location ^~ /v4 {
  proxy_pass $scheme://v4;
}

location ~* "^/v[0-9]+" {
    rewrite ^/v[0-9]+/(.*)$ /$latestVersion/$1;
    proxy_pass $scheme://$latestUpstream;
}

最后一个位置块适用于v0-9,但是当数字是v11之类的多个数字时,即使我使用的是+,也无法捕获。

对此的任何帮助都会很棒。真的很困惑。谢谢!

1 个答案:

答案 0 :(得分:0)

在以下块中:

location ~* "^/v[0-9]+" {
    rewrite ^/v[0-9]+/(.*)$ /$latestVersion/$1;
    proxy_pass $scheme://$latestUpstream;
}

rewrite语句执行隐式rewrite ... last,这意味着URI最终由location ^~ /v5块处理,在此块中呈现proxy_pass语句,几乎多余。有关rewrite语法,请参阅this document

当URI显示为单独的版本字符串尾随rewrite时,/无法匹配,例如/v11

您需要使版本字符串后面的/可选。尝试:

location ^~ /v {
    rewrite ^/v[0-9]+(/.*)$ /$latestVersion$1 last;
}

正则表达式location阻止可能是不必要的,所以我用较短的前缀location替换了(location last语法)

我添加了rewrite后缀,以明确/v5的意图。

编辑:回复您的评论

区分URI /v51/(即没有尾随location)仅使用前缀/块是有问题的。如果URI 始终在版本字符串后面(至少)有一个尾随/,只需在现有的{{{}}中添加一个尾随location即可轻松解决1}}阻止。

但假设您需要使用/v5/v51之类的短URI,则应将解决方案切换为正则表达式location块。

请注意,正则表达式location块的计算方式不同,并且该顺序很重要。您可能需要在其他正则表达式location块之前移动这些location块,以防止它们被配置文件中的其他代码覆盖。

例如:

location ~* ^/v5(/|$) {
    proxy_pass $scheme://v5;
}
location ~* ^/v4(/|$) {
    proxy_pass $scheme://v4;
}
location ~* ^/v[0-9] {
    rewrite ^/v[0-9]+(/.*)$ /$latestVersion$1 last;
}

请注意,修饰符更改为~*,它引入了正则表达式(并且还使其不区分大小写 - 这对您来说可能重要也可能不重要)。