Nginx 的 location 匹配规则

约定

本文以 Nginx 1.17.6 主线版为准。

引言

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

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

最常见的错误

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

1server { 2 listen 80; 3 4 location / { 5 return 600; 6 } 7 8 location /a { 9 return 601; 10 } 11 12 location ^~ /a/b { 13 return 602; 14 } 15 16 location /a/b/c { 17 return 603; 18 } 19 20 location ~ (star)$ { 21 return 604; 22 } 23}

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

1import requests 2 3 4class App: 5 @staticmethod 6 def main(): 7 pre = 'http://192.168.1.162' 8 uris = ['/a/b/c/star', '/a/b/d/star'] 9 for uri in uris: 10 resp = requests.get(pre + uri) 11 code = resp.status_code 12 print('请求 {:s} 的结果的状态码为 {:d}'.format(uri, code)) 13 resp.close() 14 15 16if __name__ == '__main__': 17 App.main()

输出结果为:

1请求 /a/b/c/star 的结果的状态码为 604 2请求 /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 带 ^~,所以不再匹配正则。

匹配规则

给出几个定义:

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

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

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

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

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

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )