Nginx 的 location 匹配规则

Stella981
• 阅读 736

约定

本文以 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。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
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
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Stella981 Stella981
3年前
Nginx 常见问题整理
Nginx常见问题整理1、Nginx常见问题1、相同server\_name多个虚拟主机优先级访问根据文件名顺序优先读取。使用ip访问的时候,也是根据文件名顺序优先读取。2、location匹配优先级进行普通字符精
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Nginx配置中Location的优先级
根据Nginx的官方文档,Location标签一共有四个修饰符,分别是:(1):表示完全匹配;(2)^~:匹配URI的前缀,并且后面的正则表达式不再匹配,如果一个URI同时满足两个规则的话,匹配最长的规则;(3)~:匹配正则表达式,大小写敏感;(4)~:匹配正则表达式,大小写不敏感;优先级:(1
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这