oldme 博客

锲而舍之,朽木不折;锲而不舍,金石可镂

Nginx 的 location 的匹配规则

oldme create: 2023-03-30

location 是 Nginx 的块级指令,用作匹配不同的 URL 请求做不同的业务处理。其中较为难理解的是 location 的匹配顺序。

序言

location 在 Nginx 中用来匹配从客户端发送过来的不同请求,从而匹配不同的资源,是 Nginx 中一个很重要的指令。location 有两种语法:

location @name {
    ...
}

第一种方式比较简单, @name 表示自己定义的一个名称,通常用作 Nginx 的内部跳转:

error_page 404 = @404;
location @404 {
    proxy_pass http://oldme.net;
}

如示例,当访问的 URL 不存在时,就会重定向到 http://oldme.net

第二种方式是分为四个部分: location + 匹配符号 + URL + 处理逻辑。其中匹配规则又分为四种,且五种匹配方式有着不同的优先级顺序。这种方式是最常见的匹配方式,也是本文的重点所在。而四种匹配方式又分为普通匹配和正则匹配,如果你不了解正则,可以先学习一下:正则表达式从入门到高级

location [ = | ~ | ~* | ^~ ] URL {
    ...
}

普通匹配

精准匹配

精准匹配使用 = 匹配符号,表示只有 URL 全部对应才能匹配到。精准匹配优先级最高,一旦命中,直接返回。

location = /list {
    ...
}

http://oldme.net/list 匹配成功
http://oldme.net/list/ 匹配失败(注意最后的/)
http://oldme.net/list/1 匹配失败
http://oldme.net/article/list/1 匹配失败

前缀匹配

前缀匹配使用 ^~ 匹配符号,表示匹配 URL 的前缀部分。会优先匹配前缀最长的 location,且区分大小写。命中前缀后直接返回,不在执行后续的匹配规则,优先级仅次于精准匹配,优先级第二。

location ^~ /pre {
    [pre]
}


location ^~ /pre/pre2 {
    [pre2]
}

http://oldme.net/pre 匹配[pre]
http://oldme.net/pre123 匹配[pre]
http://oldme.net/Pre 不匹配
http://oldme.net/pre/pre2/1 匹配[pre2]

前缀匹配也可以使用无符号的匹配方式,但是优先级最低,处于正则之后,排在第四。

使用 ^~无符号匹配 的最大区别就是一个处于正则匹配之前,一个处于正则匹配之后。

location /pre {
    [pre]
}

Nginx 如果运行在 Windows 下,精准匹配和前缀匹配是不区分大小写的。

正则匹配

正则匹配两种匹配方式的优先级都处在第三方,低于 ~^ 前缀匹配,高于 无符号前缀匹配。匹配顺序就按照文件中的顺序来匹配。

~ 代表的是区分大小写的正则匹配,~* 代表不区分大小写的正则匹配。

location ~ /Pre/ {
    ...
}

http://oldme.net/Pre/ 匹配
http://oldme.net/Pre 不匹配
http://oldme.net/pre 不匹配
http://oldme.net/article/Pre/ 匹配

location ~* /Pre/ {
    ...
}

http://oldme.net/Pre/ 匹配
http://oldme.net/pre/ 匹配
http://oldme.net/Pre 不匹配
http://oldme.net/pre 不匹配
http://oldme.net//article/pre/ 匹配

匹配顺序

  1. = 精准匹配
  2. ^~ 前缀匹配,会优先匹配最长的前缀
  3. ~~* 正则匹配,匹配顺序按照文件中的位置
  4. 无符号前缀匹配,会优先匹配最长的前缀

location 结尾带不带/

location 结尾带不带斜杠(/)是有区别的。如果 location 结尾带斜杠,例如:

location /exp/ {
    // 处理以 /exp/ 开头的 URL 的配置
}

那么这个 location 将匹配所有以 /exp/ 开头的 URL,包括 /exp/ 本身和 /exp/a/exp/bURL。注意,这里的斜杠表示一个目录,即表示匹配以 /exp/ 开头的 URL,并且后面必须跟着一个目录或者 URL 末尾。

如果 location 结尾不带斜杠,例如:

location /exp {
    // 处理以 /exp 开头的 URL 的配置
}

那么这个 location 将匹配所有以 /exp 开头的 URL,包括 /exp 本身和 /exp/a/exp/bURL。这里的斜杠表示一个字符,即表示匹配以 /exp 开头的 URL,并且后面可以跟着任意字符。

评论

欢迎您的回复 取消回复

您的邮箱不会显示出来,*必填

本文目录