玩转Nginx Location:实用技巧与避坑指南

 3个月前     2  

文章目录

Nginx是一款高性能的Web服务器,而Location块作为Nginx配置的核心之一,为我们提供了强大的路由跳转能力。本文将深入探讨Nginx Location块的实用技巧与避坑指南,以便能更好的了解Nginx服务器配置。

location指令

玩转Nginx Location:实用技巧与避坑指南

在上述语法中,  、~ *^~都是 location 用于实现访问控制的前缀,且在使用时只能选择一种,当然也可以不设置前缀。

玩转Nginx Location:实用技巧与避坑指南

merge_slashes是一个用于配置的指令,用于控制是否合并多个连续的斜杠(/) 。当merge_slashes设置为on时,Nginx将合并请求中的多个连续斜杠为单个斜杠。这是比较有用的,因为在Web请求中,有时候会由于用户输入、URL构造等原因导致出现多个斜杠。例如,example.com//path/to/resource中的双斜杠。

根据上表的描述,可将 location 根据不同前缀的使用方式,分为以下几种:

前缀字符串 :常规匹配(空)、  精确匹配、^~ 匹配上这条之后不再进行正则表达式匹配

正则表达式:  区分大小写的正则匹配、 ~ * 不区分大小写的正则匹配

用于内部调整的命名location:@

精确匹配

精准匹配指的就是用户访问的 URI 与配置的 URI 完全一致的情况,才会执行其后的指令块,示例配置如下 。

server {
    listen 8081;
    location / {
    }
    location = /Test1 {
        return 200 'exact match!';
    }
}

匹配成功则立即处理,nginx停止搜索其他匹配。

[root@dev conf]# curl http://192.168.2.129:8081/Test1
exact match!

常规匹配(最大前缀匹配)

由于 location 可以同时定义多个,当一个配置文件中同时出现多个 location 时,普通常规location 之间遵循“最大前缀匹配”原则,匹配最多的那个将会执行。

location /Test1/Test2 {
    return 200 'longest prefix string match!';
}
location /Test1 {
    return 200 'prefix string match!';
}

示例如下:

[root@dev conf]# curl 192.168.2.129:8081/Test1/Test2
longest prefix string match!

这里需要特别注意的一点是,当普通 location 与正则 location 同时存在时,如果正则 location 匹配成功,则不会执行普通 location 的最大前缀 location 匹配结果。

正则匹配

Nginx 配置文件中,多个正则 location 之间按照nginx.conf的顺序依次匹配正则表达式,且只要匹配成功就不会继续匹配后面定义的正则 location , 在实际应用中要注意正则 location 在配置文件中的书写顺序 。

#它匹配以/Test1/结尾的URL路径
location ~ /Test1/$ {
    return 200 'first regular expressions match!';
}
location ~* /Test1/(\w+)$ {
    return 200 'longest regular expressions match!';
}
[root@dev conf]# curl http://192.168.2.129:8081/3/Test1/
first regular expressions match!
[root@dev conf]# curl http://192.168.2.129:8081/Test1/2
longest regular expressions match!

详细匹配流程

当一个URL请求到Nginx之后,首先会进行全部的前缀字符串Location匹配,location 的匹配并不完全按照其在配置文件中出现的顺序来匹配,请求URI 会按如下规则进行匹配:

  1. 1. 先精准匹配 = ,精准匹配成功则会立即执行,然后停止其他类型匹配;
  2. 2. 没有精准匹配成功时,进行前缀匹配。先查找带有 ^~ 的前缀匹配,带有 ^~ 的前缀匹配成功则立即停止其他类型匹配;
  3. 3. = 和 ^~ 均未匹配成功前提下,进行普通前缀匹配成功则会暂存最长匹配的前缀字符串,继续查找正则匹配,查找正则匹配 ~ 和 ~\* 。当同时有多个正则匹配时,按其在配置文件中出现的先后顺序优先匹配,命中则立即停止其他类型匹配;
  4. 4. 所有正则匹配均未成功时,返回步骤 3中暂存的普通前缀匹配结果
玩转Nginx Location:实用技巧与避坑指南

实践问题

当把所有的Location放一起,Nginx的配置文件内容如下:

 server {
    listen 8081;
    location /Test1/Test2 {
        return 200 'longest prefix string match!';
    }
    location = /Test1 {
        return 200 'exact match!';
    }
    location ~ /Test1/$ { #以/Test1/结尾的URL
        return 200 'first regular expressions match!';
    } 
    location ~* /Test1/(\w+)$ { # ~* 正则匹配,不区分大小写
        return 200 'longest regular expressions match!';
    }
    location ^~ /Test1/ {
        return 200 'stop regular expressions match!';
    }
    location /Test1 {
        return 200 'prefix string match!';
    }}

可以思考下访问URL:

  • /Test1
  • /Test1/
  • /Test1/Test2
  • /Test1/Test2/
  • /test1/Test2

会返回什么内容呢?

[root@dev nginx2]# curl 192.168.2.129:8081/Test1
exact match![root@dev nginx2]#
[root@dev nginx2]# curl 192.168.2.129:8081/Test1/
stop regular expressions match![root@dev nginx2]#
[root@dev nginx2]# curl 192.168.2.129:8081/Test1/Test2
longest regular expressions match![root@dev nginx2]#
[root@dev nginx2]# curl 192.168.2.129:8081/Test1/Test2/
longest prefix string match![root@dev nginx2]#
[root@dev nginx2]# curl 192.168.2.129:8081/Test1/Test2/
longest prefix string match![root@dev nginx2]#

proxy_pass避坑指南

proxy_pass是Nginx反向代理常用的一个指令,但是指令存在新手很容易踩的坑,就是 proxy_pass 中的URL是否有‘/’ 的问题。

proxy_pass的URL带有 /

在nginx中配置proxy_pass时,当在proxy_pass后面的url加上了/,相当于是绝对根路径,nginx转发时,会将原uri去除location匹配表达式后的内容拼接在proxy_pass中url之后。

#测试地址:http://192.168.2.129/test/tes.jsp
#场景一:
location ^~ /test/ {
    proxy_pass http://192.168.2.129:8081/server/;
}
#代理后实际访问地址:http://192.168.2.129:8081/server/tes.jsp
#场景二:
location ^~ /test {
    proxy_pass http://192.168.2.129:8081/server/;
}
#代理后实际访问地址:http://192.168.2.129:8081/server//tes.jsp
#场景三:
location ^~ /test/ {
    proxy_pass http://192.168.2.129:8081/;
}
#代理后实际访问地址:http://192.168.2.129:8081/tes.jsp

proxy_pass的URL不带/

proxy_pass配置中url末尾不带/时,如url中不包含path(只有ip和端口),则直接将原uri拼接在proxy_pass中url(ip和端口)之后;如url中包含path,则将原uri去除location匹配表达式后的内容拼接在proxy_pass中的url之后。

#测试地址:http://192.168.2.129/test/tes.jsp
 #场景一:
 location ^~ /test/{
    proxy_pass http://192.168.2.129:8081/server; #url中包含path:/server
 }
#代理后实际访问地址:http://192.168.2.129:8081/servertes.jsp
#场景二:
location ^~ /test {
    proxy_pass http://192.168.2.129:8081/server;
}
代理后实际访问地址:http://192.168.2.129:8081/server/tes.jsp
#场景三:
location ^~ /test/ {
    proxy_pass http://192.168.2.129:8081; #url中不包含path
}
代理后实际访问地址:http://192.168.2.129:8081/test/tes.jsp
#场景四:
location ^~ /test {
    proxy_pass http://192.168.2.129:8081;
}
代理后实际访问地址:http://192.168.2.129:8081/test/tes.jsp

root和alias指令区别

在 Nginx 配置中,root 和 alias 都是用于指定静态资源的根目录路径,但它们在处理路径匹配和返回文件时存在一些差异。

玩转Nginx Location:实用技巧与避坑指南

root 指令

例如,假设我们有以下配置:

location /static/ {
    root /var/www/;
}

当收到的请求是 http://example.com/static/image.jpg 时,Nginx 会查找文件系统中的 /var/www/static/image.jpg 并返回该文件。

这里需要注意的是,root 指令会将匹配的 URL 路径直接映射到文件系统中的相对路径, 也就是将请求 URL全 路径附加到根位置来形成要提供的最终文件路径。

alias指令

alias 指令表示别名的意思,会将匹配的 URL 路径替换为指定的文件系统路径。

location /static/ {
    alias /var/www/;
}

在上面的例子中,/static/ 被替换为 /var/www/ ,当收到的请求是 http://example.com/static/image.jpg 时,Nginx 会查找文件系统中的 /var/www/image.jpg 并返回该文件。

综上所述,root 用于直接映射 URL 路径到文件系统中的相对路径,而 alias 允许在返回文件时修改 URL 路径的部分或全部。

暂无评论

暂无评论...