详细解析 nginx uri 如何匹配 location 规则
location 是 nginx 配置中出现最频繁的配置项,一个 uri 是如何与多个 location 进行匹配的?
在有多个 location 都匹配的情况下,如何决定使用哪一个 location 作为匹配结果?
清晰内部机制之后,疑问自然迎刃而解。
location 规则类型
根据官方文档,location 配置语法如下
Syntax: location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default: —
Context: server, location
其语法对应了 location 规则的 5 种类型:
prefix
前缀匹配规则,如果 uri 包含相应的前缀,则匹配成功。
语法上, location 之后单纯跟上 uri,没有任何操作符。
location /api/v1 {
....
}
exact uri
完全匹配规则,如果 uri 和规则完全相同,则匹配成功。
语法上,使用 = 操作符。
location = /api/v1 {
....
}
case-sensitive regex
区分大小写的正则表达式匹配规则,如果 uri 与正则表达式相匹配,则匹配成功。
正则表达式使用 pcre library,语法和 perl 兼容。
语法上,使用 ~ 操作符。
这里有一个细节,uri 作为一个 string,只要 regex 匹配其中的一部分,即可算作匹配。
比如有如下的规则,
location ~ /api/v1 {
....
}
可以匹配 uri
- /api/v1/login
- /pod/api/v1
如果想要匹配整个 string,则要使用 ^ $
。
比如,
location ~ ^/api/v1.*$ {
....
}
可以匹配 uri
- /api/v1/login
不可以匹配
- /pod/api/v1
case-insensitive regex
规则同上,区别只在于,正则表达式不区分大小写。
不区分大小写的正则表达式匹配规则,如果 uri 与正则表达式相匹配,则匹配成功。
语法上,使用 ~*
操作符。
location ~* /api/v1 {
....
}
disable regex prefix
匹配流程与 prefix 规则相同,有一点区别在于,如果最长匹配是当前规则,则之后不进行 正则表达式 规则的搜索。
这一点可能有些难以理解,后面会详细讲解。
语法上,使用 ^~
操作符。
location ^~ /api/v1 {
....
}
uri 如何选择 location
前面讲到,location 规则有 5 种类型,那么 uri 如何在多种不同类型的 location 规则之间,
最终选择到唯一的 location 规则呢?
根据官方文档的描述,详细规则如下:
- 如果存在 exact uri 规则与 uri 匹配,至步骤 6
- 在所有 prefix 规则和 disable regex prefix 规则中进行匹配(与这些规则定义的顺序无关),
如果没有匹配到规则,至步骤 3;如果存在匹配的规则,选择出最长匹配 uri 的规则:- 如果规则是 disable regex prefix 类型,至步骤 6
- 如果规则是 prefix 类型,记住当前匹配的 prefix 规则,选为待定,至步骤 3
- 逐个遍历 case-sensitive regex 规则和 case-insensitive regex 规则(按照这些规则定义的前后顺序):
- 如果规则匹配,则遍历终止,至步骤 6
- 如果规则没有匹配,则继续
- 如果之前有 prefix 规则条目被选择为待定,至步骤 6
- 匹配失败,返回404,结束
- 选择当前规则,使用其配置,结束
图解
draw by draw.io, 源文件
FAQ
有人可能会困惑,如果 prefix 与 disable regex prefix 规则相同,比如,
location /static/ {
....
}
location ^~ /static/ {
....
}
最终会匹配哪一条规则?是否应该继续查找 regex 规则?
实际上,这种情况 nginx 会报错,nginx: [emerg] duplicate location "/static/" in /etc/nginx/conf.d/location.conf
,
所以这种情况是不用考虑的。
示例
示例项目在 nginx example,
参考 readme 文件,在本地启动 nginx server。
其中对 nginx 的配置如下,使用 curl 进行检测。
exact uri 规则先于所有规则(与规则定义的顺序无关),所以这里匹配了 = /
exact uri 规则而不是 /
prefix 规则。
$ curl http://localhost:8080/
uri "/": exact match "location = /"
exact uri 规则先于所有规则(与规则定义的顺序无关),所以这里没有匹配 ^~ /static/
disable regex prefix 和 ~* \.PNG$
,~ \.png$
regex 规则。
正是因为 exact uri 规则的这种属性,如果有高频率使用的 uri,建议使用 exact uri 匹配,加快匹配速度。
$ curl http://localhost:8080/static/logo.png
uri "/static/logo.png": exact uri match "location = /static/logo.png"
prefix 规则中,匹配 uri 长度最长的规则会选中,所以没有选中 /
prefix 规则。同样的,从这一点来看,/api
和 /api/
是不一样的。
$ curl http://localhost:8080/api
uri "/api": prefix match "location /api"
$ curl http://localhost:8080/api/
uri "/api/": prefix match "location /api/"
$ curl http://localhost:8080/api/v1
uri "/api/v1": prefix match "location /api/"
如果匹配了 ^~ /static/
disable regex prefix 规则,则不再去搜索之后的 regex 规则。
$ curl http://localhost:8080/static/thinkpad.png
uri "/static/thinkpad.png": disable regex prefix match "location ^~ /static/"
在 regex 规则的匹配中,定义的先后顺序是重要的,所以 ~ \.png$
case-sensitive 规则永远不会被匹配。
$ curl http://localhost:8080/files/large.png
uri "/files/large.png": case-insesitive regex match "location ~* \.PNG(dollar)"
$ curl http://localhost:8080/files/large.PNG
uri "/files/large.PNG": case-insesitive regex match "location ~* \.PNG(dollar)"
即使先匹配了 /api/
prefix 规则作为待定,但是也匹配了 regex 规则,优先使用 regex 规则。
$ curl http://localhost:8080/api/v1/file/logo.png
uri "/api/v1/file/logo.png": case-insesitive regex match "location ~* \.PNG(dollar)"
存在 /
prefix 规则是有益的,收容所有未明确定位的 uri,再做错误处理。
$ curl http://localhost:8080/no-where
uri "/no-where": prefix match "location /"
写在最后
详细解析 nginx uri 如何匹配 location 规则的更多相关文章
- Nginx日志参数、location匹配规则、设置密码
1.三个参数 a)$http_referer:记录此次请求是从哪个链接访问过来的: 是直接访问,还是从其他网站跳转过来的. 例如:访问:http://www.etiantian.com/,其页面首页是 ...
- Nginx location指令匹配顺序规则
location匹配命令 1. “= ”,字面精确匹配, 如果匹配,则跳出匹配过程.(不再进行正则匹配) 2. “^~ ”,最大前缀匹配,如果匹配,则跳出匹配过程.(不再进行正则匹配) 3. 不带任何 ...
- nginx教程1:location 匹配规则
worker_process # 表示工作进程的数量,一般设置为cpu的核数 worker_connections # 表示每个工作进程的最大连接数 server{} # 块定义了虚拟主机 liste ...
- nginx里面的location 规则匹配
nginx location语法 ~ # 区分大小写的正则匹配 location ~ \.(gif|jpg|png|js|css)$ { #规则D } ~* # 不区分大小写的正则匹配(和~的功能相同 ...
- Nginx配置请求转发location及rewrite规则
一个示例: location = / { # 精确匹配 / ,主机名后面不能带任何字符串 [ configuration A ] } location / { # 因为所有的地址都以 / 开头,所以这 ...
- nginx配置文件结构及location块语法规则
一. nginx配置文件结构介绍 二. location语法规则: 用法示例: location [=|~|~*|^~] /uri/ { … } # 讲解如下: 1. = 开头表示精确匹配 2. ...
- Nginx rewrite跳转 location匹配
目录: 一.常用的Nginx 正则表达式 二.location 三.rewrite 一.常用的Nginx 正则表达式 1 ^ :匹配输入字符串的起始位置 2 $ :匹配输入字符串的结束位置 3 * : ...
- [日常] nginx与location规则
=========================================================================2018年3月28日 记录: location = / ...
- Nginx Location规则
Nginx由内核和模块组成,其中内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端的请求映射到一个location block,而location是Nginx配置中的一个指令 ...
随机推荐
- CameraAPI中的 自定义照相功能
前几天的项目需要使用CameraAPI自己定义照相机,之前用过的二维码也要自己写底层代码,于是总结一下使用CameraAPI的几点事项.现在由于JDK7.0及其以上版本的官方文档已经不再推荐使用cam ...
- docker18.ce harbor 安装
Harbor 是什么? harbor VMware 开发的一个容器镜像仓库,harbor的功能提供用户权限管理.镜像复制等功能,提高使用的registry的效率. 安装最新版的docker可以参考d ...
- SDN 第四次上机作业
1.建立以下拓扑,并连接上ODL控制器. 2.利用ODL下发流表,使得h3在10s内ping不通h1,10s后恢复. 3.借助Postman通过ODL的北向接口下发流表,再利用ODL北向接口查看已下发 ...
- Alpha冲刺报告(8/12)(麻瓜制造者)
今日已完成 邓弘立: 完成了对主页UI控件的更新 符天愉: 没有完成留言模块,只是完成了留言的查询并且将留言多级回复格式化,同时和队友一起部署了商品发布的接口 江郑: 经过了这几天的编码,需求方面的数 ...
- yield协程
1.Generator Generator , 一种可以返回迭代器的生成器,当程序运行到yield的时候,当前程序就唤起协程记录上下文,然后主函数继续操作,当需要操作的时候,在通过迭代器的next重新 ...
- SQL操作语句
SQL语句与Mysql的语句大体上比较相似.以下是sql server的一套练习题,是很好的数据库操作语句学习资料,学校的学习资料,在此整理了以下. 数据库exam:这是一个模拟电子商务,网上直销的数 ...
- table border
table的CSS为{border-collapse:collapse;border:none;},再设置td的CSS为{border:solid#000 1px;}是一个非常不错的方法. 示例: & ...
- CSS3页面布局方案
CSS3页面布局方案 Web页面中的布局,在css3之前,主要使用float属性或者position属性进行页面中的简单布局,但是使用它们也存在一些缺点,比如两栏或者多栏中如果元素的内容高度不一致,则 ...
- LNMP搭建 源码包
LNMP源码包搭建 linux CentOS-6.5-x86_64-bin-DVD1 nginx 版本1.8.0 下载地址:http://nginx.org/en/download.htm ...
- float与double的范围和精度以及大小非零比较
1. 范围 float和double的范围是由指数的位数来决定的. float的指数位有8位,而double的指数位有11位,分布如下: float: 1bit(符号位) 8bits(指数位) ...