Nginx 的 location 匹配规则

约定

本文以 Nginx 1.17.6 主线版为准。

引言

location 是 Nginx 配置中的重要一环,用来配置动静分离、反向代理等功能。

而 location 匹配规则,网上有太多错误的说法,今予以纠正并给出正确规则描述。

最常见的错误

最常见的错误之一,就是认为 ^~ 的优先级高于 ~,但实际上,我们编写如下配置:

server {
    listen    80;

    location / {
        return 600;
    }

    location /a {
        return 601;
    }

    location ^~ /a/b {
        return 602;
    }

    location /a/b/c {
        return 603;
    }

    location ~ (star)$ {
        return 604;
    }
}

并编写程序验证(或者找个 HTTP 客户端软件验证),

import requests


class App:
    @staticmethod
    def main():
        pre = 'http://192.168.1.162'
        uris = ['/a/b/c/star', '/a/b/d/star']
        for uri in uris:
            resp = requests.get(pre + uri)
            code = resp.status_code
            print('请求 {:s} 的结果的状态码为 {:d}'.format(uri, code))
            resp.close()


if __name__ == '__main__':
    App.main()

输出结果为:

请求 /a/b/c/star 的结果的状态码为 604
请求 /a/b/d/star 的结果的状态码为 602

由此可见,^~~ 并非简单的优先级关系,它们之间真正的关系是:如果匹配到的前缀匹配项中最长的一个带有 ^~,则不再匹配正则(~)。

上面的例子中,/a/b/c/fuck 匹配到的前缀匹配项有 /a 和 /a/b 和 /a/b/c,而最长的 /a/b/c 不带 ^~,所以继续匹配正则,从而匹配到 ~ (fuck)$。

而 /a/b/d/fuck 匹配到的前缀匹配项有 /a 和 /a/b,最长的 /a/b 带 ^~,所以不再匹配正则。

匹配规则

给出几个定义:

精确匹配项:带 = 修饰的 location
前缀匹配项:不带符号修饰的 location
正则匹配项:带 ~ 或 ~* 修饰的 location,它们唯一的区别是前者区分大小写,后者不区分

事实上,nginx 的 location 规则很难排出优先级,只能用文字描述:

只考虑了比较常用的 =^~~~*,其他的读者自行查阅。

  1. 先匹配 =,匹配到则停止,否则继续。
  2. 再匹配前缀匹配项,如果:
    (a)有匹配项被匹配到,且最长的匹配项有 ^~,则停止匹配;
    (b)有匹配项被匹配到,且最长的匹配项没有 ^~,则进行正则匹配;
    (c)没有匹配项被匹配到,则进行正则匹配。
  3. 然后进行正则匹配(不分长短,写在前面的优先),一旦匹配到则将其作为匹配结果(上一步的结果被替换)。

最后,如果始终没有匹配成功则返回 404。

posted @   风华神使  阅读(372)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示