一文弄懂Nginx的location匹配的实现

由于团队在进行前后端分离,前端接管了 Nginx 和 node 层,在日常的工作中,跟 Nginx 打交道的时候挺多的。其中 location 是使用最多和改动最多的地方。之前对 location 的匹配规则是一知半解的。为了搞明白 location 是如何匹配的,特意花了点时间查了些资料,总结此文。希望能给大家带来帮助。

语法规则

location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }

语法规则很简单,一个location关键字,后面跟着可选的修饰符,后面是要匹配的字符,花括号中是要执行的操作。

修饰符

  • = 表示精确匹配。只有请求的 url 路径与后面的字符串完全相等时,才会命中。
  • ~ 表示该规则是使用正则定义的,区分大小写。
  • ~* 表示该规则是使用正则定义的,不区分大小写。
  • ^~ 表示如果该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查找。

匹配过程

对请求的 url 序列化。例如,对%xx等字符进行解码,去除 url 中多个相连的/,解析 url 中的.,..等。这一步是匹配的前置工作。

location 有两种表示形式,一种是使用前缀字符,一种是使用正则。如果是正则的话,前面有~或~*修饰符。

具体的匹配过程如下:

首先先检查使用前缀字符定义的 location,选择最长匹配的项并记录下来。

如果找到了精确匹配的 location,也就是使用了=修饰符的 location,结束查找,使用它的配置。

然后按顺序查找使用正则定义的 location,如果匹配则停止查找,使用它定义的配置。

如果没有匹配的正则 location,则使用前面记录的最长匹配前缀字符 location。

基于以上的匹配过程,我们可以得到以下两点启示:

  1. 使用正则定义的 location 在配置文件中出现的顺序很重要。因为找到第一个匹配的正则后,查找就停止了,后面定义的正则就是再匹配也没有机会了。
  2. 使用精确匹配可以提高查找的速度。例如经常请求/的话,可以使用=来定义 location。

示例
接下来我们以一个例子来具体说明一下匹配过程。

假如我们有下面的一段配置文件:

location = / {
  [ configuration A ]
}

location / {
  [ configuration B ]
}

location /user/ {
  [ configuration C ]
}

location ^~ /images/ {
  [ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ {
  [ configuration E ]
}

请求/精准匹配 A,不再往下查找。

请求/index.html匹配 B。首先查找匹配的前缀字符,找到最长匹配是配置 B,接着又按照顺序查找匹配的正则。结果没有找到,因此使用先前标记的最长匹配,即配置 B。

请求/user/index.html匹配 C。首先找到最长匹配 C,由于后面没有匹配的正则,所以使用最长匹配 C。

请求/user/1.jpg匹配 E。首先进行前缀字符的查找,找到最长匹配项 C,继续进行正则查找,找到匹配项 E。因此使用 E。

请求/images/1.jpg匹配 D。首先进行前缀字符的查找,找到最长匹配 D。但是,特殊的是它使用了^~修饰符,不再进行接下来的正则的匹配查找,因此使用 D。这里,如果没有前面的修饰符,其实最终的匹配是 E。大家可以想一想为什么。

请求/documents/about.html匹配 B。因为 B 表示任何以/开头的 URL 都匹配。在上面的配置中,只有 B 能满足,所以匹配 B。

location @name 的用法

@用来定义一个命名 location。主要用于内部重定向,不能用来处理正常的请求。其用法如下:

location / {
  try_files $uri $uri/ @custom
}
location @custom {
  # ...do something
}

上例中,当尝试访问 url 找不到对应的文件就重定向到我们自定义的命名 location(此处为 custom)。

值得注意的是,命名 location 中不能再嵌套其它的命名 location。

URL 尾部的/需不需要

关于 URL 尾部的/有三点也需要说明一下。第一点与 location 配置有关,其他两点无关。

location 中的字符有没有/都没有影响。也就是说/user/和/user是一样的。

如果 URL 结构是https://domain.com/的形式,尾部有没有/都不会造成重定向。因为浏览器在发起请求的时候,默认加上了/。虽然很多浏览器在地址栏里也不会显示/。这一点,可以访问baidu验证一下。

如果 URL 的结构是https://domain.com/some-dir/。尾部如果缺少/将导致重定向。因为根据约定,URL 尾部的/表示目录,没有/表示文件。所以访问/some-dir/时,服务器会自动去该目录下找对应的默认文件。如果访问/some-dir的话,服务器会先去找some-dir文件,找不到的话会将some-dir当成目录,重定向到/some-dir/,去该目录下找默认文件。可以去测试一下你的网站是不是这样的。

总结

location 的配置有两种形式,前缀字符和正则。查找匹配的时候,先查找前缀字符,选择最长匹配项,再查找正则。正则的优先级高于前缀字符。

正则等查找是按照在配置文件中的顺序进行的。因此正则等顺序很重要,建议越精细的放的越靠前。

使用=精准匹配可以加快查找的顺序,如果根域名经常被访问等话建议使用=。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • nginx 配置location匹配规则实例讲解

    nginx的配置指令的作用域可以分为 main,server,location这3个种,实际上这3者不是依次包含的关系,而是相互独立的关系,比如一个只具有main级别作用域的指令,是不能写在某个server或者location内的,模块的某个指令可以同时具有main,server,location这3种作用域,另外每个模块有 main,srv,loc这3个级别的配置,一个模块的main级别的配置对所有的server和location都是共享的,srv级别的配置对所有 location都是共享的,

  • 详解nginx中location、rewrite用法总结

    一.location用法总结 location可以把不同方式的请求,定位到不同的处理方式上. 1.location的用法 location ~* /js/.*/\.js 以 = 开头,表示精确匹配:如只匹配根目录结尾的请求,后面不能带任何字符串. 以^~ 开头,表示uri以某个常规字符串开头,不是正则匹配 以~ 开头,表示区分大小写的正则匹配; 以~* 开头,表示不区分大小写的正则匹配 以/ 开头,通用匹配, 如果没有其它匹配,任何请求都会匹配到 location的匹配顺序是"先匹配正则,再匹配

  • 详解Nginx之Location配置(Location匹配顺序)

    location有"定位"的意思, 主要是根据Uri来进行不同的定位.在虚拟主机的配置中,是必不可少的. location可以把网站的不同部分,定位到不同的处理方式上. 1.location的基础语法 location [=|~|~*|^~] patt { } =:严格匹配.如果这个查询匹配,那么将停止搜索并立即处理此请求. ~:为区分大小写匹配(可用正则表达式). ~*:为不区分大小写匹配(可用正则表达式). ^~:如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那

  • Nginx配置之location的匹配优先级浅析

    前言 Nginx 配置中的 server 块中的 location 用来匹配请求 URI,以便对不通的 URI 进行不通的处理. location 类型 和 成功匹配的条件 location = expression {} 精准匹配,只有 URI 和 expression 完全相同,才算匹配成功: location expression {} 普通匹配,只要 URI 前部分的字符与 expression 相同就算匹配成功: location ^~ expression {} 普通匹配,只要 UR

  • 深入理解Nginx中Server和Location的匹配逻辑

    Server的匹配逻辑 Nginx在决定请求由哪个server块执行时,主要关注的是server块中的listen和server_name两个字段 listen指令 listen字段定义server响应的ip和端口,如果没有明确配置listen字段,默认监听0.0.0.0:80(root)或者0.0.0.0:8080(非root) listen可以被配置为: 一个ip和端口的组合 一个单独的ip,默认监听80端口 一个单独的端口,默认监听所有的ip接口 一个Unix socket路径 其中最后一

  • 一文弄懂Nginx的location匹配的实现

    由于团队在进行前后端分离,前端接管了 Nginx 和 node 层,在日常的工作中,跟 Nginx 打交道的时候挺多的.其中 location 是使用最多和改动最多的地方.之前对 location 的匹配规则是一知半解的.为了搞明白 location 是如何匹配的,特意花了点时间查了些资料,总结此文.希望能给大家带来帮助. 语法规则 location [ = | ~ | ~* | ^~ ] uri { ... } location @name { ... } 语法规则很简单,一个location

  • 一文弄懂Pytorch的DataLoader, DataSet, Sampler之间的关系

    以下内容都是针对Pytorch 1.0-1.1介绍. 很多文章都是从Dataset等对象自下往上进行介绍,但是对于初学者而言,其实这并不好理解,因为有的时候会不自觉地陷入到一些细枝末节中去,而不能把握重点,所以本文将会自上而下地对Pytorch数据读取方法进行介绍. 自上而下理解三者关系 首先我们看一下DataLoader.next的源代码长什么样,为方便理解我只选取了num_works为0的情况(num_works简单理解就是能够并行化地读取数据). class DataLoader(obje

  • Nginx中location匹配以及rewrite重写跳转详解

    目录 前言 一.rewrite跳转实现 二.rewrite执行顺序 三.rewrite跳转场景 四.语法与flg标记说明 五.Nginx常用的正则表达式符号 六.location 1.分类 2.常用匹配规则 3.优先级 4.示例 5.匹配规则定义 总结: 前言 rewrite功能就是使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标记实现URL重写以及重定向例如:更换域名后需要保持旧的域名能够转到新的域名上.某网页发生改变需要跳转到新的页面.网站防盗链等等需求 rewrite只能放

  • 一文弄懂JavaScript的继承方式

    目录 JavaScript中的继承方式 问:JavaScript中有几种继承方式呢 问:每种继承方式是怎么实现的呢 盗用构造函数 组合继承 原型链式继承 寄生式继承 寄生时组合继承 JavaScript中的继承方式 问:JavaScript中有几种继承方式呢 emmm...六种?五种?还是四种来着... 这次记清楚了 一共有五种继承方式 盗用构造函数 (经典继承方式 ) 组合继承 原型链式继承 寄生式继承 寄生式组合继承 问:每种继承方式是怎么实现的呢 盗用构造函数 基本思路很简单:在子类构造函

  • 让你一文弄懂Pandas文本数据处理

    目录 前言 1. 文本数据类型 1.1. 类型简介 1.2. 类型差异 2. 字符串方法 2.1. 文本格式 2.2. 文本对齐 2.3. 计数与编码 2.4. 格式判断 3. 文本高级操作 3.1. 文本拆分 3.2. 文本替换 3.3. 文本拼接 3.4. 文本匹配 3.5. 文本提取 总结 前言 日常工作中我们经常接触到一些文本类信息,需要从文本中解析出数据信息,然后再进行数据分析操作. 而对文本类信息进行解析是一件比较头秃的事情,好巧,Pandas刚好对这类文本数据有比较好的处理方法,那

  • 一文搞懂Nginx限流(简单实现)

    Nginx现在已经是最火的负载均衡之一,在流量陡增的互联网面前,接口限流也是很有必要的,尤其是针对高并发的场景.Nginx的限流主要是两种方式:限制访问频率和限制并发连接数. 限流(rate limiting)是NGINX众多特性中最有用的,也是经常容易被误解和错误配置的,特性之一.该特性可以限制某个用户在一个给定时间段内能够产生的HTTP请求数.请求可以简单到就是一个对于主页的GET请求或者一个登陆表格的POST请求. 限流也可以用于安全目的上,比如减慢暴力密码破解攻击.通过限制进来的请求速率

  • 一文弄懂MySQL索引创建原则

    目录 一.适合创建索引 1.字段的数值有唯一性限制 2.频繁作为Where查询条件的字段 3.经常Groupby和Orderby的列 4.Update.Delete的where条件列 5.Distinct字段需要创建索引 6.多表Join连接操作时,创建索引注意事项 7.使用列的类型小的创建索引 8.使用字符串前缀创建索引 9.区分度高的列适合作为索引 10.使用最频繁的列放到联合索引的左侧 11.在多个字段都要创建索引的情况下,联合索引由于单值索引 二.不适合创建索引 1.在where中使用不

  • 一文弄懂C语言如何实现单链表

    目录 一.单链表与顺序表的区别: 一.顺序表: 二.链表 二.关于链表中的一些函数接口的作用及实现 1.头文件里的结构体和函数声明等等 2.创建接口空间 3.尾插尾删 4.头插头删 5.单链表查找 6.中间插入(在pos后面进行插入) 7.中间删除(在pos后面进行删除) 8.单独打印链表和从头到尾打印链表 9.test.c 总结 一.单链表与顺序表的区别: 一.顺序表: 1.内存中地址连续 2.长度可以实时变化 3.不支持随机查找 4.适用于访问大量元素的,而少量需要增添/删除的元素的程序 5

  • 一文弄懂MySQL中redo log与binlog的区别

    目录 前言 1. 什么是redo log? 1.1 redo日志文件名 1.2 影响redo log参数 1.3 redo log大小怎么设置? 2. 什么是binlog 2.1 binlog文件名 2.2 影响binlog的参数 2.3 查看binlog 3. redo log与binlog的区别 总结 前言 MySQL中有六种日志文件,分别是:重做日志(redo log).回滚日志(undo log).二进制日志(binlog).错误日志(errorlog).慢查询日志(slow query

随机推荐