一文读懂nginx的location匹配规则

一、location的指令分为两种匹配模式 :

  • 普通字符串匹配
  • 正则匹配

二、普通匹配包含三种格式:

修饰符 参考示例 说明
location /hello/world 前缀匹配,不支持正则
= location = /hello/world 又叫精确匹配,不支持正则,匹配后既终止正则匹配又终止普通匹配
^~ location ^~ /hello/world 前缀匹配,不支持正则 ,匹配后不再进行正则匹配

三、正则匹配包含两种格式:

修饰符 参考示例 说明
~ location ~ \.jpg$ 区分大小写的正则匹配,是包含匹配,而非前缀匹配
~* location ~* \.jpg$ 不区分大小写的正则匹配,是包含匹配,而非前缀匹配

四、location匹配顺序

五、关于location匹配的一些误区

1、 location 的匹配顺序是“先匹配正则,再匹配普通”。

矫正: location 的匹配顺序其实是“先匹配普通,再“考虑”匹配正则”。注意这里的“考虑”是“可能”的意思,也就是说匹配完“普通 location ”后,有的时候需要继续匹配“正则 location ”,有的时候则不需要继续匹配“正则 location ”。两种情况下,不需要继续匹配正则 location :
( 1 )当普通 location 前面指定了“ ^~ ”,特别告诉 Nginx 本条普通 location 一旦匹配上,则不需要继续正则匹配;
( 2 )当普通location 恰好严格匹配上,不是最大前缀匹配,则不再继续匹配正则。

2、 location 的执行逻辑跟 location 的编辑顺序无关。

矫正:这句话不全对,“普通 location ”的匹配规则是“最大前缀”,因此“普通 location ”的确与 location 编辑顺序无关;但是“正则 location ”的匹配规则是“顺序匹配,且只要匹配到第一个就停止后面的匹配”

总结一句话:“正则 location 匹配让步普通 location 的严格精确匹配结果;但覆盖普通 location 的最大前缀匹配结果”

六、举个栗子

此处我用的是openresty版本的nginx,因此可以直接使用echo指令。如果是原生nginx,要使用echo指令的话,则需要自行编译安装echo-nginx-module,参考:https://github.com/openresty/echo-nginx-module#installation

    server {
        listen       80;
        server_name  localhost;
        location / {
            echo "first";
        }

        location ^~ /hello {
            echo "111111-normal";
        }

        location /hello/world {
            echo "222222-normal";
        }

        location ~ /hello/world {
            echo "333333-regex";
        }
    }

访问http://127.0.0.1/hello/world的结果如下:

分析
在这个例子中,先进行普通匹配,按照最长匹配的原则,匹配到第三个location,然后这里的修饰符是非"="或"^~",则会继续向下进行正则匹配,匹配到第四个location。

我们对上面的栗子进行稍加修改,将第三个和第四个location调换下顺序,且将location /hello/world 修改为location ^~ /hello/world 如下:

    server {
        listen       80;
        server_name  localhost;
        location / {
            echo "first";
        }

        location ^~ /hello {
            echo "111111-normal";
        }

        location ~ /hello/world {
            echo "333333-regex";
        }

        location ^~ /hello/world {
            echo "222222-normal";
        }

    }

这时候再访问http://127.0.0.1/hello/world的结果如下:

由此可以说明,匹配的顺序是“先普通,再“考虑”正则”,而"="或"^~"这两个修饰符会终止“考虑”正则。看到这里,是不是就清晰了很多呢。

posted @ 2022-03-19 17:05  wangqingyong  阅读(1166)  评论(0编辑  收藏  举报