深入理解 Nginx Location 匹配规则

1,719 阅读2分钟

概述

平时使用 Nginx 的过程中,进行最多的可能就是 server 的配置, server 块中通过 listen 指令设置对端口的监听,server_name 指令根据域名进行匹配,确定执行的 server 指令块

进入到 server 块中;在一个 server 块中会配置一个或者多个 location 块。通过对请求 URI 的匹配确定执行的 location 指令块。location 指令只会匹配URI,不会匹配后面的参数。

Location 配置语法

    Syntax : location [~|~*|^~|=] uri {...}
           : location @name {...}
       
    Default : -
    Context : server location

location 指令可以分为以下 3 类:

  • 前缀字符串匹配
  • 正则表达式匹配
  • 用于内部跳转的命名location @

主要需要掌握前两条的规则,以及 location 块的匹配流程

前缀字符串匹配

前缀字符串匹配根据有无修饰符、修饰符的不同可以分为三种不同的情况

  • 无修饰符:常规匹配 URI 的开头
  • ^~ 修饰符:常规匹配 URI 的开头,不同的是,如果匹配成功则不会进行后续的正则匹配。
  • = 修饰符:精确地匹配 URI ,完全一样才会匹配的上
    // 等于号(=)修饰符:精确匹配,
    location = /aaa {
        return 200 'SUCCESS';
    }
    
    // 无修饰符:一般常规匹配
    location /aaa {
        return 200 'SUCCESS';
    }
    
    // ^~修饰符 : 匹配上后则不在进行后续的正则表达式匹配
    location ^~ /aaa {
        return 200 'SUCCESS';
    }

正则表达式匹配

正则表达式匹配以 ~ 修饰符开始,后面如果跟 * 表示忽略大小写。

  • ~*:忽略大小写
  • ~:大小写敏感
    // ~* : 忽略大小写
    location ~* ss/index.html$ {
        return 200 'SUCCESS';
    }
    
    // ~ : 大小写敏感
    location ~ ss/index.html$ {
        return 200 'SUCCESS';
    }

匹配流程

Nginx_location_20.jpg

整个匹配其实是优先级最高的是精确匹配(=),如果存在精确匹配匹配成功,则使用精确匹配的location

精确匹配不存在,则进行前缀字符串匹配,首先找到最长匹配的前缀字符串,然后看是否以 ^~ 开头,顺序很重要。先确定最长匹配。然后看是否以 ^~ 开头。以 ^~ 开头的如果不是最长匹配肯定不会使用

确定了最长匹配之后 根据是否以 ^~ 开头来决定是否进行正则匹配。以 ^~ 开头则使用该最长匹配,未以 ^~ 开头,则继续进行正则表达式匹配。

正则表达式匹配时,注意 location 在 nginx.conf 中的前后顺序,在前的优先。如果正则表达式匹配成功,则使用正则表达式匹配的结果,否则使用之前最长匹配的结果。