跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 请教一个 nginx rewrite 指令匹配到的部分消失的问题
未分類
7 9 月 2020

请教一个 nginx rewrite 指令匹配到的部分消失的问题

请教一个 nginx rewrite 指令匹配到的部分消失的问题

資深大佬 : gwy15 3

我想实现一个 “根据不同的 header 中的 Accept-Language 返回不同的文件” 功能,我写的配置文件如下:

map $http_accept_language $locale {     default         "en-US";     ~*en            "en-US";     ~*zh            "zh-CN"; }  server {     listen 80;     server_name _;      location / {         rewrite_log on;         rewrite ^/(.*)$ /prerendered/$locale/$1;     }      location /prerendered/en-US {         root /usr/share/nginx/html;         # try_files $uri $uri/ $uri.html /prerendered/en-US/index.html =404;     }      location /prerendered/zh-CN {         root /usr/share/nginx/html;         # try_files $uri $uri/ $uri.html /prerendered/zh-CN/index.html =404;     } } 

大体思路就是利用 map 定义一个 $locale 变量,然后 rewrite 到对应目录。

文件结构:

/usr/share/nginx/html/prerendered ├── en-US                                content: │   ├── a.html                           a en-US │   └── index.html                       index en-US └── zh-CN     ├── a.html                           a zh-CN     └── index.html                       index zh-CN 

curl 命令和结果:

$ curl http://127.0.0.1/a.html a en-US $ curl http://127.0.0.1/a.html -H 'Accept-Language: en' index en-US $ curl http://127.0.0.1/a.html -H 'Accept-Language:zh' index zh-CN 

从第二个命令开始,路径就被错误地重定向到了 /prerendered/en-US/,后面的 a.html 消失了。

nginx 对第二个命令的日志:

2020/09/09 09:45:16 [notice] 29#29: *4 "^/(.*)$" matches "/a.html", client: 172.17.0.1, server: _, request: "GET /a.html HTTP/1.1", host: "127.0.0.1" 2020/09/09 09:45:16 [notice] 29#29: *4 rewritten data: "/prerendered/en-US/", args: "", client: 172.17.0.1, server: _, request: "GET /a.html HTTP/1.1", host: "127.0.0.1" 

可以看到,这个 rewrite 规则是命中了的,但是替换的时候后面的 $1 却没有替换上;而且只有 Accept-Language 包含 zh/en 才会出现,如果是 空 或者es(默认 map 到 en ),a.html 还是正常替换的。

求助各位这是哪里出现的问题?

大佬有話說 (6)

  • 資深大佬 : superrichman

    location 又没有定义$1 的值,后面那节就是空的,重定向没毛病

  • 主 資深大佬 : gwy15

    @superrichman 谢谢回答,但是好像不是这样的 XD

    在 stackoverflow 上有大佬解释了下,大概是;
    rewrite 部分匹配到的组,在计算 replacement 时由于懒计算会再进行 map 部分的匹配,如果正则匹配成功 $1 就会被重置,因此 $1 会变为空串。这里可以用命名组解决:

    rewrite ^/(?<myuri>.*)$ /prerendered/$locale/$myuri last;

  • 資深大佬 : ysc3839

    直接用 try_files 是没问题:
    “`
    location / {
    try_files /prerendered/$locale$uri =404;
    }
    “`

    对于“匹配任意 URL 然后进行 rewrite”的情况,使用 try_files 的话性能更好。rewrite 应该在需要匹配复杂规则时才使用。

  • 主 資深大佬 : gwy15

    @ysc3839 这里是我简化过的可重现 demo,实际上 rewrite 是在一个 if 块里面,匹配到爬虫 UA 才会 rewrite 。谢谢你。

  • 資深大佬 : ysc3839

    再者,就算要用 rewrite 实现“匹配任意 URL”,直接用
    rewrite ^ /prerendered/$locale$uri;
    即可

    因为你本来就可以通过 $uri 这个变量访问到 URL,完全没必要再匹配一次。
    “^” 是匹配开头,单独一个“^”也就等价于“匹配任意字符串”。

  • 資深大佬 : superrichman

    @gwy15 是我理解错了,学到新东西了谢谢

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具