首页 文章

nginx - 重写指令如何与标志一起匹配位置?

提问于
浏览
0

应该跟随nginx配置是死循环吗?

location / {
    # url rewrites
    rewrite ^/(.*).jsp$ /$1.html last;

    try_files $uri $uri/ =404;
}

根据文档似乎应该,但在测试中,它似乎与以下相同:

rewrite ^/(.*).jsp$ /$1.html break;

@Update

关于 last ,nginx doc说:

它开始搜索与重写的URL匹配的新位置 .

The questions are:

  • 这是什么意思?这是否意味着搜索下一个 location 指令?

  • 如果当前 last 所在的位置只有1 location ,它应该停止还是......?

1 回答

  • 4

    为了解释这一点,让我们来看看这个示例配置:

    server {
        listen 80;
        server_name localhost;
    
        location / {                   #  Location #1
            root /some/path;
        }
    
        location ~ ^/(foo|bar|baz) {   #  Location #2
    
            rewrite ^/foo /bar;        #  Rewrite rule #1
            rewrite ^/bar /baz break;  #  Rewrite rule #2
            rewrite ^/baz /qux last;   #  Rewrite rule #3
            rewrite ^/qux /foo;        #  Rewrite rule #4
    
            root /another/path;
        }
    }
    
    • 如果我们尝试在浏览器中打开 http://localhost/foo 会发生什么情况:

    Nginx解析请求,获取URI部分( /foo ),然后查找与此请求的URI匹配的所有位置 . 在这种情况下,两个位置都匹配URI,但由于 Location #2 是使用正则表达式定义的,因此Nginx将选择它超过 Location #1 ,或者换句话说,将使此位置成为请求上下文 . 您可以在documentation中找到有关位置优先级的一些信息 .

    现在确定了位置,Nginx开始逐个执行在其中找到的所有重写指令 .

    在执行 Rewrite rule #1 之后,URI从 /foo 更改为 /bar ,并且Nginx继续执行下一个重写指令,即 Rewrite rule #2 .

    在执行 Rewrite rule #2 之后,URI再次被更改,这次是从 /bar/baz . 并且由于使用了 break 标志,Nginx将不会在此位置执行其余的重写指令 . 所以这次都不会执行 Rewrite rule #3Rewrite rule #4 .

    因此, /another/path/baz 将显示在浏览器中 .

    如果我们直接请求 http://localhost/bar ,将提供相同的文件 . 仅在这种情况下 Rewrite rule #1 将不会被执行(因为 /bar^/foo 不匹配) .

    • 现在,如果我们尝试打开 http://localhost/baz ,过程将如下所示:

    Location #2 将被选为上下文,因为它具有更高的优先级并匹配请求 . Rewrite rule #1Rewrite rule #2 都将被忽略,因为 /baz^/foo^/bar 不匹配 .

    Rewrite rule #2break 标志将与规则本身一起被忽略,因为只有当标志所属的规则重写URI时,标志才会影响进程 .

    Rewrite rule #3 与URI匹配,因此将执行 . 该规则将URI从 /baz 更改为 /qux ,然后整个过程被中断,因为 last 标志启动 . 它的作用基本上是告诉Nginx停止处理请求并从一开始就开始,但这次使用重写的URI .

    所以Nginx再次开始寻找合适的位置,但这次URI是 /qux ,而不是 /baz . 由于 Location #2/qux 不匹配,因此选择 Location #1 作为请求上下文 . 因此 /some/path/qux 服务(注意路径) .

    这里最有趣的部分是我们在 Location #2 的上下文中开始并且因为 last 标志而在 Location #1 结束 .

    这一切都是如此 . 是的,如果只有一个位置,它将再次使用(假设它与重写的URI匹配),但这次使用新的(重写的)URI . 是的,有可能导致无限循环和不幸的配置 . 虽然Nginx会在10个左右的周期后检测并中断它 .

    附:如果你想知道 Rewrite rule #4 ,在这个配置中它是"dead directive" . 它永远不会被执行 .

相关问题