说明

在 Nginx 中,location 指令是用于定义如何响应不同请求的 URI。Nginx 会根据请求的 URI 与 location 块中的模式进行匹配,以确定应该应用哪个配置块来处理该请求。location 解析过程说明如下:

  1. 精确匹配:
    • Nginx 首先会尝试找到与请求的 URI 完全匹配的 location 块。例如,有一个 location = /test 的配置,当请求的 URI 是 /test 时,则应用这个配置。
  2. 前缀匹配:
    • 没有找到精确匹配的 location 块,Nginx 会尝试寻找以请求的 URI 开头的前缀匹配。在多个前缀匹配的情况下,Nginx 会选择最长的那个前缀。例如,对于 URI:/test/page,location /test/ 会比 location /te 更优先。
  3. 正则表达式匹配:
    • 如果仍然没有找到匹配的 location 块,Nginx 会尝试使用正则表达式进行匹配。正则表达式 location 块以 ~(区分大小写)或 ~*(不区分大小写)开始。如果存在多个正则表达式匹配,Nginx 会选择第一个匹配项,因此正则表达式的顺序很重要。
  4. 默认匹配(如果都没有匹配):
    • 如果所有的精确匹配、前缀匹配和正则表达式匹配都失败,Nginx 会使用默认的 location 块(通常是不带任何参数的 location 块)。
  5. 处理匹配到的 location:
    • 一旦 Nginx 找到了匹配的 location 块,它就会根据该块中的指令来处理请求。这可能包括代理请求到另一个服务器、提供静态文件、执行重写等。

总结:精确匹配具有最高的优先级,其次是前缀匹配(顺序不重要,按匹配到的长短来确定),然后是正则表达式匹配(顺序很重要,如同时存在多个相同类型的匹配时,选择第一个匹配项),最后是默认匹配。

Location解析过程图

配置定义

修饰符的说明

  • = :表示精确匹配,只有请求的URI与模式完全相等时才会被匹配。

  • ~:表示执行一个正则表达式匹配,且区分大小写。

  • ~*:表示执行一个正则表达式匹配,但不区分大小写。

  • ^~:如果URI以指定模式开始,则使用这个location,不再检查其他更长的正则location,此时以默认的根目录开始。

  • @:定义一个命名的location,不能被直接访问,可以用在内部重定向(比如 try_files 或者 error_page )中。

  • 上下文配置

    1
    一般情况下放在server块内部定义,也可以嵌套在另一个location块内部。

默认配置

  • 查看配置nginx.conf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    [root@RockyLinux9 ~]# vim /usr/local/nginx/conf/nginx.conf
    http {
    ...
    server {
    ...

    location / {
    root html;
    index index.html index.htm;
    }
    }
    }
  • 访问Web(配置了域名解析)

精准匹配(=)

修改配置nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

[root@RockyLinux9 ~]# vim /usr/local/nginx/conf/nginx.conf
http {
...
server {
...

# 添加精准匹配块
location = /index.html {
root /var/www/html;
index index.html index.htm;
}

location / {
root html;
index index.html index.htm;
}
}
}

前缀匹配

  • 创建测试目录

    1
    2
    3
    4
    5
    6

    [root@RockyLinux9 ~]# mkdir /usr/local/nginx/html/linuxjsz
    [root@RockyLinux9 ~]# cat /usr/local/nginx/html/linuxjsz/index.html
    <html>
    This directory is /usr/local/nginx/html/linuxjsz.
    </html>
  • 配置文件未进行任何修改。http://ip/linuxjsz可正常访问。

  • 修改nginx.conf,添加配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    [root@RockyLinux9 ~]# vim /usr/local/nginx/conf/nginx.conf
    http {
    ...
    server {
    ...

    # 添加精准匹配块
    location = /index.html {
    root /var/www/html;
    index index.html index.htm;
    }

    # 添加前缀匹配块
    location /linuxjsz {
    index index.html index.htm;
    }

    location / {
    root html;
    index index.html index.htm;
    }
    }
    }
  • 再次访问http://ip/linuxjsz,发现结果和未配置一样。

  • 总结:

    • 两次的访问结果虽然一样,但是,要理解的是,即使不为需要访问的目录显式地设置一个 location 块,Nginx仍然会按照其默认的 location / 块来处理对那个目录的请求
    • 所以,当明确知道要访问的某个目录时,不需要在 location 块中通过前缀匹配来显式指定整个目录路径,除非有特定的路由需求或要应用某些特定的指令到该目录及其子路径。

正则表达式匹配(~)

  • 创建测试目录

    1
    2
    3
    4
    5
    6

    [root@RockyLinux9 ~]# mkdir /var/www/images/
    [root@RockyLinux9 ~]# cat /var/www/images/index.html
    <html>
    This directory is /var/www/images.
    </html>
  • 修改nginx.conf,添加配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    [root@RockyLinux9 ~]# vim /usr/local/nginx/conf/nginx.conf
    http {
    ...
    server {
    ...

    # 添加精准匹配块
    location = /index.html {
    root /var/www/html;
    index index.html index.htm;
    }

    # 添加前缀匹配块
    location /linuxjsz {
    index index.html index.htm;
    }

    # 添加正则表达式匹配
    location ~ /imag(.*)$ {
    root /var/www;
    index index.html index.html;
    }

    location / {
    root html;
    index index.html index.htm;
    }
    }
    }
    # 保存配置文件并重载服务
    [root@RockyLinux9 ~]# nginx -s reload
  • 访问http://ip/images/ , 可以返回了正则表达式匹配到的目录

保存配置文件并重载服务
[root@RockyLinux9 ~]# nginx -s reload
访问Web(配置了域名解析)
图片

总结:上图可以看到,已经返回了正则表达式匹配到的目录。

以上,就是一些对于 location 块的基本测试,如需了解更多,可以与我进行交流