关于nginx:nginx-location匹配和优先级

一 语法和优先级

语法
location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }

location 前面第一个参数是可选的。
=是准确匹配。当匹配到了,则完结。
^是正则匹配,辨别大小写。
^*是正则匹配,不辨别大小写。
^~是前缀匹配。

第一个参数不填,前面跟着/uri。此时也是前缀匹配。只是优先级在正则匹配之后。
第一个参数不填,前面跟着/。此时也是前缀匹配。只是优先级在所有匹配之后。也就是都匹配不到,则匹配该location。
示例配置如下:

location /uri {
    # ...
}
location / {
    # ...
}

优先级:
当配置文件中有=,优先匹配该location,匹配到了,则完结匹配。匹配不到,则先找是否有^~
^~,则优先匹配该location。匹配到了,则完结匹配。匹配不到,则依照配置文件程序,从上到下匹配。
先匹配第一个正则,匹配到了,则完结。
匹配不到,则往下匹配。
如果没有一个正则都匹配不到,则匹配/uri。有,则匹配该location,而后完结。如果没有,则匹配/。有,则匹配该location,而后完结。没有,则提醒404。

所以把=放到第一个地位,能进步匹配速度。

另外,location的所有匹配,都只对不带参数的申请的uri进行匹配的。
也就是/test/test?a=1是一样的。

二 测试代码

1 准确匹配

拜访 http://localhost/test.png,因为有=,所以优先匹配,而后完结。

// 输入4
server {
    listen       80;
    server_name  localhost;
    location ^~ /test.png {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 1;
    }
    location ~ /test.png {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 2;
    }
    location ~* /test.png  {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 3;
    }
    location = /test.png {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 4;
    }
}

2 前缀匹配

^~: 优先前缀匹配
/: 前缀匹配

最长匹配:指的是前缀匹配/,当有多个匹配的时候,先记住以后匹配,持续往下匹配,如果没有正则和优先前缀匹配,则始终匹配到最初一个location,而后应用最长匹配到的location。

拜访http://localhost/test/txt/tt,匹配到第一个后,持续往下匹配。因为没有其余正则和优先前缀匹配,所以始终到第三个匹配,匹配到了,则完结。没匹配到,则以下面匹配的为准。
当拜访http://localhost/test/txt/,则会把三个location都匹配完,才抉择最长匹配到的location。
所以,如果应用/前缀匹配的时候,绝对会慢一些。

server {
    listen       80;
    server_name  localhost;
    location /test/ {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 1;
    }
    location /test/txt/ {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 2;
    }
    location /test/txt/t {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 3;
    }
}

/前缀匹配上面有优先前缀匹配或者正则,匹配到了,则完结。
当拜访http://localhost/test/txt/,到第二个location后,则完结匹配。

// 输入2
server {
    listen       80;
    server_name  localhost;
    location /test/ {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 1;
    }
    location ^~ /test/txt/ {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 2;
    }
}

当拜访http://localhost/test/,匹配到正则后,则完结匹配。不会再往下匹配第三个location。

// 输入2
server {
    listen       80;
    server_name  localhost;
    location /test/ {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 1;
    }
    location ~ /test/ {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 2;
    }
    location ~ /test/txt/ {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 3;
    }
}

优先匹配^~跟在配置文件的程序无关。以下两种状况后果是一样的。
当拜访 http://localhost/test.png,都输入1

// demo1
server {
    listen       80;
    server_name  localhost;
    location ^~ /test.png {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 1;
    }
    location ~ /test.png  {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 2;
    }
}
// demo2
server {
    listen       80;
    server_name  localhost;
    location ~ /test.png {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 2;
    }
    location ^~ /test.png {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 1;
    }
}

3 正则匹配

正则匹配,从上到下,匹配到了,则完结。
拜访 http://localhost/test.png,因为匹配到了第一个正则,所以就完结了。页面输入2

server {
    listen       80;
    server_name  localhost;
    location ~ /test.png {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 2;
    }
    location ~ /test.png  {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 3;
    }
    location ~ /test.png {
        add_header Content-Type 'text/html;charset=utf-8';
        return 200 4;
    }
}

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理