Nginx location 匹配优先级问题

2022-12-20 0 35

最近在配置网站静态资源访问的时候,发现出现404,对nginx的优先级还是不够理解。

location匹配顺序

示例配置代码

user  root root;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

#worker_rlimit_nofile 655350;
events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;
    client_max_body_size 1024m;

    #gzip  on;

    server {
        listen       8090;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404             /404.html;

        # redirect server error pages to the static page /50x.html
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        location /aa-web {
            #root /home/abc/nginx/html;
            index  index.html index.htm;
            try_files $uri $uri/ /aa-web/index.html;
        }

        location ^~ /aa-server {
                proxy_pass http://192.168.1.80:18081;
                proxy_redirect off;
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                chunked_transfer_encoding off;
                client_max_body_size 100m;
                # rewrite ^/aa-server/?(.*)$ /$1 break;
                #proxy_port off;
                #proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

nginx有两层指令来匹配请求 URI 。第一个层次是 server 指令,它通过域名、ip 和端口来做第一层级匹配,当找到匹配的 server 后就进入此 server 的 location 匹配。

location 的匹配并不完全按照其在配置文件中出现的顺序来匹配,请求URI 会按如下规则进行匹配:

1、先精准匹配 = ,精准匹配成功则会立即停止其他类型匹配;
2、没有精准匹配成功时,进行前缀匹配。先查找带有 ^~ 的前缀匹配,带有 ^~ 的前缀匹配成功
则立即停止其他类型匹配,普通前缀匹配(不带参数 ^~ )成功则会暂存,继续查找正则匹配;
3、= 和 ^~ 均未匹配成功前提下,查找正则匹配 ~ 和 ~* 。当同时有多个正则匹配时,按其在配置文件中出现的
先后顺序优先匹配,命中则立即停止其他类型匹配;
4、所有正则匹配均未成功时,返回步骤 2 中暂存的普通前缀匹配(不带参数 ^~ )结果

location 支持的语法 location [=||*|^~|@] pattern { … },乍一看还挺复杂的,来逐个看一下。
以上规则简单总结就是优先级从高到低依次为(序号越小优先级越高):

1. location =    # 精准匹配
2. location ^~   # 带参前缀匹配
3. location ~    # 正则匹配(区分大小写)
4. location ~*   # 正则匹配(不区分大小写)
5. location /a   # 普通前缀匹配,优先级低于带参数前缀匹配。
6. location /    # 任何没有匹配成功的,都会匹配这里处理

location修饰符类型

**「=」 修饰符:要求路径完全匹配**
server {
    server_name website.com;
    location = /abcd {
    […]
    }
}
*^/abcd$这个正则表达式表示字符串必须以/开始,以$结束,中间必须是abcd*
- http://website.com/abcd匹配(完全匹配)
- http://website.com/ABCD不匹配,大小写敏感
- http://website.com/abcd?param1¶m2匹配
- http://website.com/abcd/不匹配,不能匹配正则表达式
- http://website.com/abcde不匹配,不能匹配正则表达式
**「~*」不区分大小写的正则匹配**

server {
server_name website.com;
location ~* ^/abcd$ {
[…]
}
}

- 1. http://website.com/abcd匹配 (完全匹配)
- 2. http://website.com/ABCD匹配 (大小写不敏感)
- 3. http://website.com/abcd?param1¶m2匹配
- 4. http://website.com/abcd/ 不匹配,不能匹配正则表达式
- 5. http://website.com/abcde 不匹配,不能匹配正则表达式
**「^~」修饰符:前缀匹配**
如果该 location 是最佳的匹配,那么对于匹配这个 location 的字符串, 该修饰符不再进行正则表达式检测。注意,这不是一个正则表达式匹配,它的目的是优先于正则表达式的匹配
查找的顺序及优先级
当有多条 location 规则时,nginx 有一套比较复杂的规则,优先级如下:

- 精确匹配 =
- 前缀匹配 ^~(立刻停止后续的正则搜索)
- 按文件中顺序的正则匹配 ~或~*
- 匹配不带任何修饰的前缀匹配。
这个规则大体的思路是
先精确匹配,没有则查找带有 ^~的前缀匹配,没有则进行正则匹配,最后才返回前缀匹配的结果(如果有的话)

案例分析

案例 1

server {
server_name website.com;
location /doc {
return 701; # 用这样的方式,可以方便的知道请求到了哪里
}
location ~* ^/document$ {
return 702; # 用这样的方式,可以方便的知道请求到了哪里

}

}

curl -I website.com:8080/document HTTP/1.1 702
按照上述的规则,第二个会有更高的优先级
案例2

server {
server_name website.com;
location /document {
return 701;
}
location ~* ^/document$ {
return 702;
}
}

curl -I website.com:8080/document
第二个匹配了正则表达式,优先级高于第一个普通前缀匹配
案例 3

server {
server_name website.com;
location ^~ /doc {
return 701;
}
location ~* ^/document$ {
return 702;
}
}

curl http://website.com/document HTTP/1.1 701
第一个前缀匹配^~命中以后不会再搜寻正则匹配,所以会第一个命中

案例 4

server {
server_name website.com;
location /docu {
return 701;
}
location /doc {
return 702;
}
}

curl -I website.com:8080/document 返回 HTTP/1.1 701,

server {
server_name website.com;
location /doc {
return 702;
}
location /docu {
return 701;
}
}

curl -I website.com:8080/document 依然返回 HTTP/1.1 701
前缀匹配下,返回最长匹配的 location,与 location 所在位置顺序无关

案例 5

server {
listen 8080;
server_name website.com;

location ~ ^/doc[a-z]+ {
    return 701;
}

location ~ ^/docu[a-z]+ {
    return 702;
}

}

curl -I website.com:8080/document 返回 HTTP/1.1 701
把顺序换一下

server {
listen 8080;
server_name website.com;

location ~ ^/docu[a-z]+ {
    return 702;
}

location ~ ^/doc[a-z]+ {
    return 701;
}

}


curl -I website.com:8080/document 返回 HTTP/1.1 702
正则匹配是使用文件中的顺序,找到返回
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

本站所有资源均来自于互联网用户收集上传,仅供个人交流学习使用,版权属原著所有

自由社 文章 Nginx location 匹配优先级问题 https://www.freeman.work/1259.html

常见问题

相关文章

发表评论
暂无评论