Nginx location 匹配规则详解
最近团队在做前后端分离,前端这边接手了 Nginx 和 node 层。说实话,跟 Nginx 打交道的次数一下子多了起来,尤其是 location 配置,几乎每次上线都要改一改。
location 匹配规则看似简单,实则有不少细节容易忽略。今天就把我总结的 location 匹配规则分享出来,希望能帮到有需要的小伙伴。
先说语法
location 的语法其实挺简单的:
1 | location [ = | ~ | ~* | ^~ ] uri { ... } |
一个 location 关键字,后面跟着可选的修饰符,然后是要匹配的路径,花括号里是要执行的配置。
修饰符有四种:
=- 精确匹配,请求路径必须和后面的字符串完全一样才能命中~- 正则匹配,区分大小写~*- 正则匹配,不区分大小写^~- 前缀匹配,如果这个是最佳匹配,就不再继续查找正则了
匹配过程才是重点
知道语法只是第一步,真正让人头疼的是:这么多 location 放在一起,到底谁先匹配?
匹配过程大致是这样的:
第一步:先找前缀字符定义的 location,记录下最长匹配的那条。
第二步:如果找到了精确匹配(就是用了 = 修饰符的),直接用它的配置,结束查找。
第三步:按顺序找正则定义的 location,找到第一个匹配的就停,用它的配置。
第四步:如果正则都没匹配上,就用第一步记录的最长前缀匹配。
这里有两条很重要的结论:
正则 location 的顺序很重要!因为找到第一个匹配的正则就停了,后面定义的正则写得再好也没机会了。
用精确匹配
=可以提高查找速度。比如经常请求根路径/,可以用location = /来定义。
举个栗子
光说规则太抽象了,来看个实际配置:
1 | location = / { |
咱们逐个请求来分析:
请求
/→ 匹配 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 能匹配上。
@name 是干嘛的
@ 用来定义一个命名 location,主要用于内部重定向,不能处理正常请求。
1 | location / { |
当访问的 url 找不到对应文件时,就会重定向到 @custom 这个命名 location。挺好用的,特别是做 fallback 逻辑的时候。
不过要注意,命名 location 里面不能再嵌套其他命名 location。
结尾斜杠的事儿
关于 URL 结尾的 /,有三点值得说:
location 配置里有没有
/其实没影响,/user/和/user是一样的。如果 URL 是
https://domain.com/这种形式,结尾有没有/都不会重定向。因为浏览器发请求时默认会加上。如果 URL 是
https://domain.com/some-dir/,结尾如果少了/会触发重定向。因为按照约定,结尾有/表示目录,没有表示文件。服务器找不到some-dir文件时,会把它当成目录,重定向到/some-dir/。
小结
最后总结一下优先级,从高到低:
=精确匹配(最高优先级,立即停止)^~前缀匹配(停止正则搜索)~和~*正则匹配(按配置文件顺序)- 普通前缀匹配(最长匹配原则,最低优先级)
搞清楚这些规则后,配置 Nginx location 就更加得心应手了。希望这篇总结对大家有所帮助。