渡渡鸟_linux 2019-07-07 22:14 采纳率: 0%
浏览 109

nginx的rewrite指令中break flag疑问

nginx 配置

server {
    listen 8080 default_server ;
    root /opt/website/write ;
    rewrite_log on ;
    location /location1/ {
        rewrite /location1/(.*) /test/$1 last ;
        return 200 "location1\r\n" ;
    }
    location /location2/ {
        rewrite /location2/(.*) /test/$1 break ;
        return 200 "location2\r\n" ;
    }
    location /test/ {
        return 200 "test\r\n" ;
    }
    location / {
        return 200 "null\r\n" ;
    }
}
  • 创建目录和index.html

# mkdir -p /opt/website/write/{location1,location2,test}

# ls /opt/website/write/|awk '{print $1".index" > "/opt/website/write/"$1"/index.html"}'

  • 测试:

[root@centos-81 ~]# curl -s 192.168.1.81:8080/location2/
test

[root@centos-81 ~]# curl -s 192.168.1.81:8080/location2/index.html
test.index

疑问:

  • 对第一个请求结果有疑问,照着官方文档描述,break 不会跳出location层级,应该直接寻找 test/目录下的index.html,理论上返回的是 test.index。不知道是啥原因返回了 test

  • 在第二个请求中也证明了是寻找 /test/目录下的文件,而不是跳出location。

  • 写回答

1条回答

  • CSDN-Ada助手 CSDN-AI 官方账号 2022-10-25 19:18
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:
    • 给你找了一篇非常好的博客,你可以看看是否有帮助,链接:nginx反向代理和rewrite进行解决跨域问题 去掉url中的一部分字符串,通过nginx正则生成新的url
    • 除此之外, 这篇博客: nginx(一)中的 rewrite中的break和last 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

      两个指令用法相同,但含义不同,需要放到rewrite规则的末尾,用来控制重写后的链接是否继续被nginx配置执行(主要是rewrite、return指令)。

      示例1(连续两条rewrite规则):

      server{
          listen 80; 
          server_name test.com;
          root /tmp/123.com;
      
          rewrite /1.html /2.html ;
          rewrite /2.html /3.html ;
          
      }
      

      当我们请求1.html时,最终访问到的是3.html,两条rewrite规则先后执行。
      break和last在location {}外部
      格式:rewrite xxxxx break;

      示例2(增加break):

      server{
          listen 80; 
          server_name test.com;
          root /tmp/123.com;
      
          rewrite /1.html /2.html break;
          rewrite /2.html /3.html;
      }
      

      当我们请求1.html时,最终访问到的是2.html
      说明break在此示例中,作用是不再执行break以下的rewrite规则。

      但,当配置文件中有location时,它还会去执行location{}段的配置(请求要匹配该location)。

      示例3(break后面还有location段):

      server{
          listen 80; 
          server_name test.com;
          root /tmp/123.com;
      
          rewrite /1.html /2.html break;
          rewrite /2.html /3.html;
          location /2.html {
              return 403;
          }
      }
      

      当请求1.html时,最终会返回403状态码,说明它去匹配了break后面的location{}配置。

      以上2个示例中,可以把break替换为last,它们两者起到的效果一模一样。
      当break和last在location{}里面
      示例4(什么都不加):

      server{
          listen 80; 
          server_name test.com;
          root /tmp/123.com;
          
          location / {
              rewrite /1.html /2.html;
              rewrite /2.html /3.html;
          }
          location /2.html
          {
              rewrite /2.html /a.html;
          }
          location /3.html
          {
              rewrite /3.html /b.html;
          }
      }
      

      当请求/1.html,最终将会访问/b.html,连续执行location /下的两次rewrite,跳转到了/3.html,然后又匹配location /3.html

      示例5(增加break):

      server{
          listen 80; 
          server_name test.com;
          root /tmp/123.com;
          
          location / {
              rewrite /1.html /2.html break;
              rewrite /2.html /3.html;
          }
          location /2.html
          {
              rewrite /2.html /a.html;
          }
          location /3.html
          {
              rewrite /3.html /b.html;
          }
      }
      

      当请求/1.html,最终会访问/2.html
      在location{}内部,遇到break,本location{}内以及后面的所有location{}内的所有指令都不再执行。

      示例6(增加last):

      server{
          listen 80; 
          server_name test.com;
          root /tmp/123.com;
          
          location / {
              rewrite /1.html /2.html last;
              rewrite /2.html /3.html;
          }
          location /2.html
          {
              rewrite /2.html /a.html;
          }
          location /3.html
          {
              rewrite /3.html /b.html;
          }
      }
      

      当请求/1.html,最终会访问/a.html
      在location{}内部,遇到last,本location{}内后续指令不再执行,而重写后的url再次从头开始,从头到尾匹配一遍规则。

      结论

      • 当rewrite规则在location{}外,break和last作用一样,遇到break或last后,其后续的rewrite/return语句不再执行。但后续有location{}的话,还会近一步执行location{}里面的语句,当然前提是请求必须要匹配该location。
      • 当rewrite规则在location{}里,遇到break后,本location{}与其他location{}的所有rewrite/return规则都不再执行。
      • 当rewrite规则在location{}里,遇到last后,本location{}里后续rewrite/return规则不执行,但重写后的url再次从头开始执行所有规则,哪个匹配执行哪个。

    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

悬赏问题

  • ¥20 求计算赫斯特(Hurst)指数
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大