因为团队在进行先后端分离,前端接管了 Nginx 和 node 层,在平常的工做中,跟 Nginx 打交道的时候挺多的。其中 location 是使用最多和改动最多的地方。以前对 location 的匹配规则是只知其一;不知其二的。为了搞明白 location 是如何匹配的,特地花了点时间查了些资料,总结此文。但愿能给你们带来帮助。html
location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
复制代码
语法规则很简单,一个location
关键字,后面跟着可选的修饰符,后面是要匹配的字符,花括号中是要执行的操做。前端
=
表示精确匹配。只有请求的 url 路径与后面的字符串彻底相等时,才会命中。~
表示该规则是使用正则定义的,区分大小写。~*
表示该规则是使用正则定义的,不区分大小写。^~
表示若是该符号后面的字符是最佳匹配,采用该规则,再也不进行后续的查找。对请求的 url 序列化。例如,对%xx
等字符进行解码,去除 url 中多个相连的/
,解析 url 中的.
,..
等。这一步是匹配的前置工做。node
location 有两种表示形式,一种是使用前缀字符,一种是使用正则。若是是正则的话,前面有~
或~*
修饰符。后端
具体的匹配过程以下:浏览器
首先先检查使用前缀字符定义的 location,选择最长匹配的项并记录下来。bash
若是找到了精确匹配的 location,也就是使用了=
修饰符的 location,结束查找,使用它的配置。服务器
而后按顺序查找使用正则定义的 location,若是匹配则中止查找,使用它定义的配置。markdown
若是没有匹配的正则 location,则使用前面记录的最长匹配前缀字符 location。前后端分离
基于以上的匹配过程,咱们能够获得如下两点启示:dom
/
的话,可使用=
来定义 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。主要用于内部重定向,不能用来处理正常的请求。其用法以下:
location / { try_files $uri $uri/ @custom } location @custom { # ...do something } 复制代码
上例中,当尝试访问 url 找不到对应的文件就重定向到咱们自定义的命名 location(此处为 custom)。
值得注意的是,命名 location 中不能再嵌套其它的命名 location。
/
需不须要关于 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/
,去该目录下找默认文件。能够去测试一下你的网站是否是这样的。
location 的配置有两种形式,前缀字符和正则。查找匹配的时候,先查找前缀字符,选择最长匹配项,再查找正则。正则的优先级高于前缀字符。
正则等查找是按照在配置文件中的顺序进行的。所以正则等顺序很重要,建议越精细的放的越靠前。
使用=
精准匹配能够加快查找的顺序,若是根域名常常被访问等话建议使用=
。