跳过正文

Nginx路径'/'匹配案例

·346 字·2 分钟
陌白
作者
陌白
一只热爱技术的码农
目录

一、不同’/‘结尾的区别
#

location /api/ {
  proxy_pass http://backend:8080/;
}
location /api/ {
  proxy_pass http://backend:8080;
}

location /api {
  proxy_pass http://backend:8080/;
}

location /api {
  proxy_pass http://backend:8080;
}

配置一:带斜杠的路径匹配和目标 URL
#

location /api/ {
    proxy_pass http://backend:8080/;
}
  • 匹配以 /api/ 开头的请求
  • 将请求转发到带有尾部斜杠的目标 URL
  • 替换匹配的路径部分
  • 例如:请求 /api/file.jpg 会被转发到 http://backend:8080/file.jpg

配置二:带斜杠的路径匹配但目标 URL 不带尾部斜杠
#

location /api/ {
    proxy_pass http://backend:8080;
}
  • 匹配以 /api/ 开头的请求
  • 将请求转发到不带尾部斜杠的目标 URL
  • 会将整个原始 URI 附加到目标 URL 后面
  • 例如:请求 /api/file.jpg 会被转发到 http://backend:8080/api/file.jpg

配置三:不带斜杠的路径匹配但目标 URL 带尾部斜杠
#

location /api {
    proxy_pass http://backend:8080/;
}
  • 匹配以 /api 开头的请求(包括 /api/api/...
  • 将请求转发到带有尾部斜杠的目标 URL
  • 替换匹配的路径部分
  • 例如:当请求/api/file.jpg时,Nginx 会将匹配的路径部分/api替换为http://backend:8080/。由于目标 URL 已经包含了尾部斜杠,而原始请求中/api之后也有一个斜杠,所以最终转发的 URL 会变成 http://backend:8080//file.jpg(注意这里有两个连续的斜杠)
  • 请求 /api 会被转发到 http://backend:8080/

这种配置可能会导致一些 Web 服务器在处理双斜杠时出现问题,虽然大多数现代服务器能够正确处理这种情况。

如果想避免这个问题,可以使用以下两种方式之一:

  1. 使用配置一(如果只需要匹配/api/开头的请求)
  2. 使用配置四,确保 proxy_pass 的 URL 不以斜杠结尾

配置四:不带斜杠的路径匹配和目标 URL 也不带尾部斜杠
#

location /api {
    proxy_pass http://backend:8080;
}
  • 匹配以 /api 开头的请求(包括 /api/api/...
  • 将请求转发到不带尾部斜杠的目标 URL
  • 会将整个原始 URI 附加到目标 URL 后面
  • 例如:请求 /api/file.jpg 会被转发到 http://backend:8080/api/file.jpg
  • 请求 /api 会被转发到 http://backend:8080/api

总结
#

  • proxy_pass 的 URL 以 / 结尾时,Nginx 会替换匹配的路径部分
  • proxy_pass 的 URL 不以 / 结尾时,Nginx 会将完整的原始 URI 附加到目标 URL
  • location /api/ 只匹配以 /api/ 开头的请求
  • location /api 匹配以 /api 开头的所有请求,包括 /api 本身

二、Nginx proxy_pass URL 末尾斜杠的影响
#

在 Nginx 配置中,proxy_pass 指令的 URL 是否以斜杠 / 结尾会对请求路径的处理产生重要影响:

有斜杠结尾的情况
#

proxy_pass 的 URL 以斜杠结尾时(如 http://backend/),Nginx 会将请求的路径部分原样附加到目标 URL 后面。

例如:

location /api/ {
    proxy_pass http://backend/;
}

当请求 /api/users 时,会被代理到 http://backend/users(注意 /api/ 被去掉了)

无斜杠结尾的情况
#

proxy_pass 的 URL 不以斜杠结尾时(如 http://backend),Nginx 会将完整的请求路径(包括 location 匹配的部分)附加到目标 URL 后面。

例如:

location /api/ {
    proxy_pass http://backend;
}

当请求 /api/users 时,会被代理到 http://backend/api/users(保留了完整路径)

实际应用示例
#

  1. 有斜杠结尾:适用于希望去掉前缀的情况
location /api/ {
    proxy_pass http://backend:8080/;  ## 请求 /api/users 会代理到 http://backend:8080/users
}
  1. 无斜杠结尾:适用于希望保留完整路径的情况
location /api/ {
    proxy_pass http://backend:8080;  ## 请求 /api/users 会代理到 http://backend:8080/api/users
}

Nginx rewrite指令
#

Nginx的rewrite指令是一个强大的URL重写工具,它允许你根据正则表达式匹配和替换URL。这个功能在网站重构、URL规范化和实现URL友好化方面非常有用。

rewrite指令基本语法
#

rewrite regex replacement [flag];
  • regex: 用于匹配URI的正则表达式
  • replacement: 替换的URI
  • flag: 可选标志,控制重写后的行为

常用的flag
#

  1. last - 停止处理当前的ngx_http_rewrite_module指令集,并开始搜索与更改后的URI相匹配的location
  2. break - 停止处理当前的ngx_http_rewrite_module指令集
  3. redirect - 返回302临时重定向
  4. permanent - 返回301永久重定向

使用示例
#

基本重写
#

location /old/ {
    rewrite ^/old/(.*)$ /new/$1 permanent;
}

这会将所有以/old/开头的请求永久重定向到/new/开头的URL。

带条件的重写
#

if (!-f $request_filename) {
    rewrite ^/(.*)$ /index.php?q=$1 last;
}

如果请求的文件不存在,将请求重写到index.php并传递原始URI作为参数。

多级重写
#

location /download/ {
    rewrite ^/download/(.*)$ /files/$1 last;
}

location /files/ {
    rewrite ^/files/(.*)$ /protected/$1 break;
}

这个例子展示了如何使用last和break标志进行多级重写。

注意事项
#

  1. 重写规则的顺序很重要,Nginx按照配置文件中的顺序处理规则
  2. 使用last标志时,Nginx会重新开始搜索location块,可能导致循环
  3. 使用break标志可以防止循环,但会停止所有重写规则的处理
  4. 在使用正则表达式时要小心,错误的表达式可能导致意外的行为

实际应用场景
#

  1. 网站迁移:将旧网站的URL结构重定向到新网站
  2. URL规范化:确保所有URL遵循一致的格式
  3. 隐藏真实路径:隐藏实际的文件路径,增强安全性
  4. 实现伪静态:将动态URL转换为静态URL格式

相关文章