Nginx Location匹配算法及请求匹配疑问:为何/tmp/foo.php请求返回Location 3a响应?
Nginx Location匹配算法及请求匹配疑问:为何/tmp/foo.php请求返回Location 3a响应?
嘿,这个问题问得特别精准,刚好戳中了Nginx location匹配里容易被忽略的嵌套location优先级细节!咱们先把你的配置贴出来,对着说更清楚:
location / { return 200 "Location 1\n"; } location ~ \.php$ { return 200 "Location 2\n"; } location /tmp { return 200 "Location 3\n"; location ~ \.php$ { return 200 "Location 3a\n"; } }
你疑惑的点是:按常规逻辑,外部的~ \.php$(Location 2)应该匹配.php结尾的请求,而且你也知道^~修饰符才会让prefix location跳过regex检查,但这里没加^~,为啥还是走到了内部的3a?
其实核心原因是Nginx的嵌套location是在父prefix location的上下文里优先匹配的,具体流程是这样的:
- 第一步,Nginx先遍历所有prefix location,计算每个location和请求
/tmp/foo.php的匹配长度:/tmp匹配了前4个字符(/tmp),/只匹配1个,所以最长匹配的prefix location是location /tmp。 - 第二步,这时候Nginx会进入这个
location /tmp的块里,然后优先检查块内的嵌套location规则,而不是直接去和外部的regex location做对比。 - 第三步,你的请求刚好以
.php结尾,完美匹配了嵌套的location ~ \.php$,所以直接触发了return 200 "Location 3a\n";,根本轮不到外部的Location 2出场。
简单说就是:当请求匹配到某个prefix location后,Nginx会先在这个location的内部规则里找匹配,内部的规则优先级高于外部的同级规则,和父prefix有没有^~没关系——^~只是用来跳过外部的regex检查,但这里是内部嵌套的regex,本来就属于父location的管辖范围,自然会先被处理。
备注:内容来源于stack exchange,提问作者Ivan Shatsky
相关产品推荐
相关产品推荐

