2019-09-17
要写 nginx 配置文件,location 是一个比较重要的指令块,匹配到的 url 会执行对应 location 块中的语句,然而 location 匹配的类型有多种,经常会不记得不同类型的匹配规则,现在在此总结一下。
=
^~
~
~*
可以看到,大体分为两大类,一种是字符串类型(第1、2、3种类型),一种是正则类型(第4、5种类型),nginx 也是把两种类型分开处理的:先按顺序扫描字符串类型的 location 块,再按顺序扫描正则类型的 location 块,其中字符串类型都是区分大小写的。
对于多个同级的 location 块,只会执行其中一个块的代码,下面说明 nginx 的匹配过程,即如何确定执行哪一个块。
先按顺序扫描字符串类型的 location 块:
=
精确匹配,会判断字符串是否完全等于 url path,如果全等,则停止剩余 location 块的匹配,执行当前块^~
优先字符串匹配,跟普通字符串匹配的规则是一样的,即判断字符串是否匹配 url path 的开头,不同的是如果匹配成功,则立即停止剩余 location 块的匹配,执行当前块如果匹配还未停止,则按顺序扫描正则类型的 location 块:
~
,如果匹配成功,则停止剩余 location 块的匹配,执行当前块~*
跟 ~
的规则是一样的,只是正则不区分大小写如果不存在能成功匹配的正则类型,则取之前记录的普通字符串匹配的匹配长度最长项的 location 块并执行。
按照这个匹配过程,能总结出不同匹配类型的优先级:
=
精确匹配 = ^~
优先字符串匹配 > ~
正则匹配 = ~*
不区分大小写的正则匹配 > 普通字符串匹配
某些类型的 location 块的顺序是有意义的,对于那些立即停止的 location 匹配类型,顺序在前的则会优先匹配到,匹配成功则不再进行后续 location 块的匹配。例如对于正则匹配来说,如果有多个正则都能匹配某个 url path,则取顺序在最前的那个执行。但是对于普通字符串匹配来说,顺序则是无意义的,因为只会匹配到其中匹配成功的 location 块中字符串长度最长的那一个。
之前一直以为 ^~
是某种正则匹配,因为它有个代表正则匹配的 ~ 号,其实不是,是字符串类型的匹配,^~ 符号的含义感觉可以理解成 “不要正则匹配”,即匹配成功了就不用进行后续正则的匹配了,用以区分跟普通字符串匹配的区别。^ 就是 “非” 的意思,就是我们平常写的正则表达式里方括号里面的 ^ 标识符。