由于团队在进行前后端分离,前端接管了Nginx和node层,在日常的工作中,跟Nginx打交道的时候挺多的。之前对location的匹配规则是一知半解的,为了搞明白location是如何匹配的,查了些资料总结此文。希望能给大家带来帮助。
语法规则
location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
语法规则很简单,一个
location
关键字,后面跟着可选的修饰符,后面是要匹配的字符,花括号中是要执行的操作。修饰符
-
=
表示精确匹配。只有请求的url路径与后面的字符串完全相等时,才会命中。 -
~
表示该规则是使用正则定义的,区分大小写。 -
~*
表示该规则是使用正则定义的,不区分大小写。 -
^~
表示如果该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查找。
%xx
等字符进行解码,去除url中多个相连的/
,解析url中的.
,..
等。这一步是匹配的前置工作。location有两种表示形式,一种是使用前缀字符,一种是使用正则。如果是正则的话,前面有
~
或~*
修饰符。具体的匹配过程如下:
首先先检查使用前缀字符定义的location,选择最长匹配的项并记录下来。
如果找到了精确匹配的location,也就是使用了
=
修饰符的location,结束查找,使用它的配置。然后按顺序查找使用正则定义的location,如果匹配则停止查找,使用它定义的配置。
如果没有匹配的正则location,则使用前面记录的最长匹配前缀字符location。
基于以上的匹配过程,我们可以得到以下两点启示:
- 使用正则定义的location在配置文件中出现的顺序很重要。因为找到第一个匹配的正则后,查找就停止了,后面定义的正则就是再匹配也没有机会了。
- 使用精确匹配可以提高查找的速度。例如经常请求
/
的话,可以使用=
来定义location。
假如我们有下面的一段配置文件:
location = / {
[ configuration A ]
}location / {
[ configuration B ]
}location /user/ {
[ configuration C ]
}location ^~ /images/ {
[ configuration D ]
}location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
请求
/
精准匹配A,不再往下查找。请求
/index.html
匹配B。首先查找匹配的前缀字符,找到最长匹配是配置B,接着又按照顺序查找匹配的正则。结果没有找到,因此使用先前标记的最长匹配,即配置B。请求
/user/index.html
匹配C。首先找到最长匹配C,由于后面没有匹配的正则,所以使用最长匹配C。请求
/user/1.jpg
匹配E。首先进行前缀字符的查找,找到最长匹配项C,继续进行正则查找,找到匹配项E。因此使用E。请求
/images/1.jpg
匹配D。首先进行前缀字符的查找,找到最长匹配D。但是,特殊的是它使用了^~
修饰符,不再进行接下来的正则的匹配查找,因此使用D。这里,如果没有前面的修饰符,其实最终的匹配是E。大家可以想一想为什么。请求
/documents/about.html
匹配B。因为B表示任何以/
开头的URL都匹配。在上面的配置中,只有B能满足,所以匹配B。location @name的用法 @用来定义一个命名location。主要用于内部重定向,不能用来处理正常的请求。其用法如下:
location / {
try_files $uri $uri/ @custom
}
location @custom {
# ...do something
}
上例中,当尝试访问url找不到对应的文件就重定向到我们自定义的命名location(此处为custom)。
值得注意的是,命名location中不能再嵌套其它的命名location。
URL尾部的
/
需不需要
关于URL尾部的/
有三点也需要说明一下。第一点与location配置有关,其他两点无关。- location中的字符有没有
/
都没有影响。也就是说/user/
和/user
是一样的。 - 如果URL结构是
https://domain.com/
的形式,尾部有没有/
都不会造成重定向。因为浏览器在发起请求的时候,默认加上了/
。虽然很多浏览器在地址栏里也不会显示/
。这一点,可以访问baidu验证一下。 - 如果URL的结构是
https://domain.com/some-dir/
。尾部如果缺少/
将导致重定向。因为根据约定,URL尾部的/
表示目录,没有/
表示文件。所以访问/some-dir/
时,服务器会自动去该目录下找对应的默认文件。如果访问/some-dir
的话,服务器会先去找some-dir
文件,找不到的话会将some-dir
当成目录,重定向到/some-dir/
,去该目录下找默认文件。可以去测试一下你的网站是不是这样的。
正则的查找是按照在配置文件中的顺序进行的。因此正则的顺序很重要,建议越精细的放的越靠前。
【一文弄懂Nginx的location匹配】使用
=
精准匹配可以加快查找的顺序,如果根域名经常被访问的话建议使用=
。推荐阅读
- 从Nginx中的服务器标题横幅中删除版本
- 如何在Ubuntu或CentOS/RHEL中安装Nginx()
- nginx加载共享库时出错(error while loading shared libraries: libpcre.so.1)
- 带有信息图表的HTTP状态代码快速指南
- 使用GoAccess的Nginx和Apache日志监控
- Nginx – 413 Request Entity Too Large(在上传wordpress主题时)
- 将IP请求重定向到域URL –测试并修复IP规范问题
- 使用Apache或Nginx在一个服务器/IP上托管多个域
- 如何将Nginx与WebSphere Application Server一起使用()