当前位置: 首页 > article >正文

Nginx(六) Nginx location 匹配顺序及优先级深究(亲测有效)

        Nginx配置文件详解请参考另一篇文章 Nginx(三) 配置文件详解 

        本篇文章主要是探讨Nginx location的匹配顺序,依照惯例,我们还是先贴结论再看测试结果。

匹配顺序

        匹配location的过程,其实可以理解成一个在众多选项中寻找最佳答案的过程。当然,“=”代表的就是正确答案,而其它情况只是相对于正确答案的最佳选项。下面我们来看具体的匹配顺序:

        1.Nginx按照location配置顺序依次进行匹配;

        2.如果请求URI部分前缀或全部与location uri匹配,先记录下来(如有匹配长度更长的则覆盖记录),继续向下匹配,再看看是否还有最佳答案备胎,最后再考虑你

        3.如果与"="选项精确匹配,则立刻停止匹配高富帅,你就是我心目中的白马王子参考测试1

        4.如果跟"^~"选项匹配成功,还要继续完成所有匹配最长匹配策略,直到找到与"^~"匹配长度最长的那个选项后再停止匹配(如果实在找不到其它的,就只能拿这个凑合了)(虽然都不帅,但我要找最有钱的那位)参考测试2

        5.如果跟"~"或"~*"任意选项匹配成功,则立刻停止(好不容易遇到一个爆发户,不拖泥带水,立刻下手)参考测试3、4

        6.完成所有匹配前面5步中,每一步但凡匹配成功都会覆盖结果记录。如果匹配过程能进入第6步,说明请求URI前缀与location uri匹配是最好的结果了最长匹配策略,最终的结果记录也就是最佳答案(在备胎中选择最佳备胎,残忍,现实)参考测试5

优先级

       结合上面的匹配顺序和所有测试过程,我们对各种匹配规则的作用优先级做个排序

优先级排序匹配规则修饰符
1精确匹配=
2指定字符串开头^~
3正则匹配~、~* 、!~、!~*、~* \.(gif|jpg|jpeg)$、~* /js/.*/\.js
4通用匹配/

下面,我们开始测试。基本配置如下

http {
    log_subrequest on;				# 开启将子请求日志记录到access.log中
    log_format format2 escape=json '{'
    					'"SN":"$sn",'                     #自定义变量sn 
					    '"http_host":"$http_host",'
					    '"remote_addr":"$remote_addr",'
					    '"time_iso8601":"$time_iso8601",'
					    '"request":"$request",'
				    	'"http_referer":"$http_referer",'
				    	'"request_time":"$request_time",'
			    		'"request_length":"$request_length",'
			    		'"status":"$status",'
			    		'"bytes_sent":"$bytes_sent",'
			    		#'"body_bytes_sent":"$body_bytes_sent",'
			    		'"user_agent":"$http_user_agent",'
				      '}';
    
    absolute_redirect on;
    server_name_in_redirect off;
    port_in_redirect on; 
    
    server {
        listen 8688;
        server_name www.read********.cn;
        access_log  logs/access.log  format2;
        error_log  logs/error.log  notice;	# 将error_log日志级别修改为notice,否则rewrite log无法记录。
        rewrite_log on;    # 开启记录请求重写日志,默认是关闭
        root pages;     # 根目录设置为psges,该目录下有index.html、test.html、one.html、two.html、three.html
        # 下面配置本次测试的指令
        ···
        ···
 
    }
}

测试1:精确匹配 "="

server {
    ···
 
    set $sn 8;
    location /test {
        set $sn 11;
        rewrite /test /t11;
    }
    location ~* /tes {
        set $sn 22;
        rewrite /test /t22;
    }
    location ~ /tes {
        set $sn 33;
        rewrite /test /t33;
    }
    location ~ /test {
        set $sn 44;
        rewrite /test /t44;
    }
    location ~* /test {
        set $sn 55;
        rewrite /test /t55;
    }
    location ^~ /tes {
        set $sn 66;
        rewrite /test /t66;
    }
    location ^~ /test.h {
        set $sn 77;
        rewrite /test /t77;
    }
    location = /test {
        set $sn 88;
        rewrite /test /t88;
    }
    location / {
        index  index.html index.htm;
    }
}
请求地址host:8688/test
请求结果404

error.log

日志输出

*697 open() "/usr/local/nginx/pages/t88" failed (2: No such file or directory)

access.log

日志输出

{"SN":"88",···,"request":"GET /test HTTP/1.1"
最终地址host:8688/t88
结论“精确匹配”优先级最高
2023/11/18 23:46:38 [notice] 16455#16455: *697 "/test" matches "/test", client: 14.145.163.156, server: www.read********.cn, request: "GET /test HTTP/1.1", host: "www.read********.cn:8688"
2023/11/18 23:46:38 [notice] 16455#16455: *697 rewritten data: "/t88", args: "", client: 14.145.163.156, server: www.read********.cn, request: "GET /test HTTP/1.1", host: "www.read********.cn:8688"
2023/11/18 23:46:38 [error] 16455#16455: *697 open() "/usr/local/nginx/pages/t88" failed (2: No such file or directory), client: 14.145.163.156, server: www.read********.cn, request: "GET /test HTTP/1.1", host: "www.read********.cn:8688"

测试2:指定字符串开头 "^~"

server {
    ···
 
    set $sn 8;
    location /test {
        set $sn 11;
        rewrite /test /t11;
    }
    location ~* /tes {
        set $sn 22;
        rewrite /test /t22;
    }
    location ~ /tes {
        set $sn 33;
        rewrite /test /t33;
    }
    location ~ /test {
        set $sn 44;
        rewrite /test /t44;
    }
    location ~* /test {
        set $sn 55;
        rewrite /test /t55;
    }
    location ^~ /tes {
        set $sn 66;
        rewrite /test /t66;
    }
    location ^~ /test.h {
        set $sn 77;
        rewrite /test /t77;
    }
    location = /test {
        set $sn 88;
        rewrite /test /t88;
    }
    location / {
        index  index.html index.htm;
    }
}
请求地址host:8688/test.ht
请求结果404

error.log

日志输出

*699 open() "/usr/local/nginx/pages/t77" failed (2: No such file or directory)

access.log

日志输出

{"SN":"77",···,"request":"GET /test.ht HTTP/1.1"
最终地址host:8688/t77
结论

虽然先匹配到了"^~ /tes",但最终还是选择了匹配长度最长的"^~ /test.h"。所以"^~"修饰符有最长匹配策略。

“指定字符串开头”匹配规则优先级排第二。

测试3:正则表达式 "~*"

server {
    ···
 
    set $sn 8;
    location /test {
        set $sn 11;
        rewrite /test /t11;
    }
    location ~* /tes {
        set $sn 22;
        rewrite /test /t22;
    }
    location ~ /tes {
        set $sn 33;
        rewrite /test /t33;
    }
    location ~ /test.ht{
        set $sn 44;
        rewrite /test /t44;
    }
    location ~* /test.ht{
        set $sn 55;
        rewrite /test /t55;
    }
    location / {
        index  index.html index.htm;
    }
}
请求地址host:8688/test.ht
请求结果404

error.log

日志输出

*702 open() "/usr/local/nginx/pages/t22" failed (2: No such file or directory)

access.log

日志输出

{"SN":"22",···,"request":"GET /test.ht HTTP/1.1"
最终地址host:8688/t22
结论

虽然"~ /test.ht"和"~* /test.ht"两个的匹配程度最高,但还是选择了首次匹配到的"~* /tes"。

“正则表达式”匹配规则但凡匹配到任意选项都会立刻终止匹配。

2023/11/19 00:10:23 [notice] 16724#16724: *702 "/test" matches "/test.ht", client: 14.145.163.156, server: www.read********.cn, request: "GET /test.ht HTTP/1.1", host: "www.read********.cn:8688"
2023/11/19 00:10:23 [notice] 16724#16724: *702 rewritten data: "/t22", args: "", client: 14.145.163.156, server: www.read********.cn, request: "GET /test.ht HTTP/1.1", host: "www.read********.cn:8688"
2023/11/19 00:10:23 [error] 16724#16724: *702 open() "/usr/local/nginx/pages/t22" failed (2: No such file or directory), client: 14.145.163.156, server: www.read********.cn, request: "GET /test.ht HTTP/1.1", host: "www.read********.cn:8688"

测试4:正则表达式 "~" 

server {
    ···
 
    set $sn 8;
    location /test {
        set $sn 11;
        rewrite /test /t11;
    }
    location ~ /tes {
        set $sn 33;
        rewrite /test /t33;
    }
    location ~* /tes {
        set $sn 22;
        rewrite /test /t22;
    }
    location ~ /test.ht{
        set $sn 44;
        rewrite /test /t44;
    }
    location ~* /test.ht{
        set $sn 55;
        rewrite /test /t55;
    }
    location / {
        index  index.html index.htm;
    }
}
请求地址host:8688/test.ht
请求结果404

error.log

日志输出

*703 open() "/usr/local/nginx/pages/t33" failed (2: No such file or directory)

access.log

日志输出

{"SN":"33",···,"request":"GET /test.ht HTTP/1.1"
最终地址host:8688/t33
结论

虽然"~ /test.ht"和"~* /test.ht"两个的匹配程度最高,但还是选择了首次匹配到的"~ /tes"。

“正则表达式”匹配规则但凡匹配到任意选项都会立刻终止匹配。

"~"和"~*"没有优先级区分。

2023/11/19 00:17:14 [notice] 16797#16797: *703 "/test" matches "/test.ht", client: 14.145.163.156, server: www.read********.cn, request: "GET /test.ht HTTP/1.1", host: "www.read********.cn:8688"
2023/11/19 00:17:14 [notice] 16797#16797: *703 rewritten data: "/t33", args: "", client: 14.145.163.156, server: www.read********.cn, request: "GET /test.ht HTTP/1.1", host: "www.read********.cn:8688"
2023/11/19 00:17:14 [error] 16797#16797: *703 open() "/usr/local/nginx/pages/t33" failed (2: No such file or directory), client: 14.145.163.156, server: www.read********.cn, request: "GET /test.ht HTTP/1.1", host: "www.read********.cn:8688"

测试5:URI前缀匹配

server {
    ···
 
    set $sn 8;
    location /test {
        set $sn 11;
        rewrite /test /t11;
    }
    location /test.h {
        set $sn 22;
        rewrite /test /t22;
    }
    location /tes {
        set $sn 33;
        rewrite /test /t33;
    }
    location / {
        index  index.html index.htm;
    }
}
请求地址host:8688/test.ht
请求结果404

error.log

日志输出

*705 open() "/usr/local/nginx/pages/t22" failed (2: No such file or directory)

access.log

日志输出

{"SN":"22",···,"request":"GET /test.ht HTTP/1.1"
最终地址host:8688/t22
结论URI前缀匹配时取匹配长度最长的那个选项为最佳选择。
2023/11/19 00:22:11 [notice] 16870#16870: *705 "/test" matches "/test.ht", client: 14.145.163.156, server: www.readerschool.cn, request: "GET /test.ht HTTP/1.1", host: "www.readerschool.cn:8688"
2023/11/19 00:22:11 [notice] 16870#16870: *705 rewritten data: "/t22", args: "", client: 14.145.163.156, server: www.readerschool.cn, request: "GET /test.ht HTTP/1.1", host: "www.readerschool.cn:8688"
2023/11/19 00:22:11 [error] 16870#16870: *705 open() "/usr/local/nginx/pages/t22" failed (2: No such file or directory), client: 14.145.163.156, server: www.readerschool.cn, request: "GET /test.ht HTTP/1.1", host: "www.readerschool.cn:8688"


http://www.kler.cn/a/132730.html

相关文章:

  • 机器学习(基础2)
  • RabbitMQ-死信队列(golang)
  • 基于单片机智能温室大棚监测系统
  • OMV7 树莓派 tf卡安装
  • C语言导航 4.1语法基础
  • 基于Java Springboot编程语言在线学习平台
  • P2239 [NOIP2014 普及组] 螺旋矩阵 题解
  • 机器学习和深度学习领域的算法和模型
  • Java中的集合内容总结——Collection接口
  • 灰度图处理方法
  • WPF异步编程
  • 手动编译GDB
  • 使用CXF调用WSDL(二)
  • ascii 码对照表
  • LeetCode704.二分查找及二分法
  • Filter和ThreadLocal结合存储用户id信息
  • 傅里叶分析(2)
  • elementui 实现树形控件单选
  • 哈希
  • 解决Redis分布式锁宕机出现不可靠问题-zookeeper分布式锁
  • kubernetes|云原生| 如何优雅的重启和更新pod---pod生命周期管理实务
  • QGIS003:【05高级数字化工具栏】-要素移动、修改、合并操作
  • Hadoop学习总结(MapRdeuce的词频统计)
  • 【原创】java+swing+mysql鲜花购物商城设计与实现
  • ATTCK实战系列——红队实战(一)
  • Alibaba Nacos注册中心源码剖析