昨天在配置 nginx 的时候遇到一个神奇的问题,见如下 nginx 配置:

map $http_accept_language $locale {
    default         "en-US";
    ~*en            "en-US";
    ~*zh            "zh-CN";
}
location / {
    rewrite ^/(.*)$ /prerendered/$locale/$1;
}

如果 header 中的 Accept-Language 没有匹配成功,走到 default$1 就可以正常地匹配 rewrite 部分的uri;但是如果其成功匹配到 en 或是 zh 时,这个 rewrite 部分的 $1 就神奇地消失了。

我在 StackOverflow 上询问之后,Richard Smith 对这个现象进行了解答:

数字(匹配组)会被最近的一次正则匹配所覆盖,当 rewrite 匹配成功后,由于懒计算,$locale 会尝试匹配;如果匹配成功,rewrite 部分的匹配组就会被覆盖成空串。

解决方法有两种:

  1. 使用命名匹配组,rewrite ^/(?<myuri>.*)$ /prerendered/$locale/$myuri last;
  2. 使用 $uri 变量,rewrite ^ /prerendered/$locale$uri last;

在这里感谢 Richard!

0 comments