nginx rewrite 参数如何正确配置使用?

99ANYc3cd6
预计阅读时长 19 分钟
位置: 首页 参数 正文

rewrite 指令是 Nginx 核心功能之一,用于根据正则表达式规则修改请求的 URI,它通常用于实现 URL 美化(伪静态)、重定向、访问控制等场景。

nginx rewrite 参数
(图片来源网络,侵删)

rewrite 指令的基本语法

rewrite 指令可以放在 serverlocationif 等配置块中。

rewrite regex replacement [flag];

参数详解:

  1. regex (必需)

    • 类型: 正则表达式。
    • 作用: 用于匹配请求的 URI(不包括查询字符串,即 后面的内容)。
    • 正则引擎: Nginx 使用 PCRE (Perl Compatible Regular Expressions) 库,因此支持大部分 Perl 风格的正则表达式。
    • 变量匹配: 可以使用 或 来表示区分大小写和不区分大小写的匹配。
      • 区分大小写匹配。
      • 不区分大小写匹配。
      • 区分大小写不匹配。
      • 不区分大小写不匹配。
    • 示例: ^/images/ 匹配以 /images/ 开头的 URI。
  2. replacement (必需)

    • 类型: 替换字符串。
    • 作用: 当 regex 匹配成功后,Nginx 会用这个字符串替换掉原始的 URI。
    • 变量引用: 可以使用 Nginx 变量,$1, $2... 来引用正则表达式中的捕获组。$& 代表整个匹配的字符串。
    • 示例: regex^/images/(.*)$replacement/img/$1,那么请求 /images/foo/bar.jpg 会被重写为 /img/foo/bar.jpg
  3. [flag] (可选)

    nginx rewrite 参数
    (图片来源网络,侵删)
    • 类型: 标志位。
    • 作用: 决定 rewrite 指令执行后的行为,例如是否继续检查后续的 rewrite 规则、是否重定向等,这是 rewrite 指令最关键的部分。

[flag] 标志位详解

标志位控制着 rewrite 的“命运”,理解它们至关重要。

last

  • 行为: 当前的 rewrite 规则执行完毕后,Nginx 停止 在当前 location 中继续执行后续的 rewrite 规则,Nginx 会用新的 URI 重新发起一次请求,并根据这个新的 URI 在 server 标签中查找匹配的 location
  • 使用场景: 通常用于在一个 location 块中完成重写,然后交由另一个 location 块处理。
  • 注意: last 可能会导致循环重写,如果配置不当会造成无限循环。

break

  • 行为: 当前的 rewrite 规则执行完毕后,Nginx 停止 在当前 location 中继续执行后续的 rewrite 规则,它不会重新发起请求,而是在当前 location 中继续处理,例如访问 location 中指定的 root 目录下的文件。
  • 使用场景: 当你只想修改 URI,并希望请求在当前 location 内部处理时使用,将 /abc 重写为 /def,然后直接访问 /def 对应的文件。
  • 注意: break 之后,Nginx 会尝试处理重写后的 URI,但不会再次触发 rewrite 指令。

redirect

  • 行为: 返回一个 302 (临时重定向) 的 HTTP 状态码给客户端。
  • 行为细节: 客户端浏览器会收到一个 302 响应,并在响应头中看到 Location 字段,其值为 replacement 指定的 URI,浏览器会根据这个地址发起一个新的 GET 请求。
  • 特点: replacement 字符串必须是完整的、以 http://https:// 开头的绝对路径,否则浏览器可能无法正确解析。
  • 使用场景: 临时性地将旧 URL 指向新 URL,例如网站维护、临时页面跳转。

permanent

  • 行为: 返回一个 301 (永久重定向) 的 HTTP 状态码给客户端。
  • 行为细节: 与 redirect 类似,但 301 重定向具有“永久性”。
  • 特点: 浏览器会缓存这个重定向关系,下次用户再访问旧 URL 时,浏览器可能会直接从缓存中读取新地址,而不会再次向服务器请求,同样,replacement 也必须是绝对路径。
  • 使用场景: URL 结构永久性变更,例如将 blog.example.com 的流量永久重定向到 www.example.com/blog

last vs. break 的核心区别

这是一个非常容易混淆的点,用一个例子就能说清楚。

假设我们有如下配置:

server {
    listen 80;
    server_name example.com;
    location /old {
        rewrite ^/old/(.*)$ /new/$1 last; # 规则1
        rewrite ^/new/(.*)$ /final/$1 break; # 规则2
        # ... 其他 location 配置
    }
    location /new {
        rewrite ^/new/(.*)$ /another/$1 last; # 规则3
        # ... 其他 location 配置
    }
    location /final {
        echo "最终匹配到 /final";
    }
}

场景1:请求 /old/test

  1. 请求进入 location /old
  2. 规则1 匹配成功,将 URI 重写为 /new/test,并使用 last 标志。
  3. last 行为: Nginx 停止在 location /old 内部继续处理,它使用新的 URI /new/test 重新发起一次查找
  4. Nginx 在 server 块中寻找匹配 /new/testlocation,找到了 location /new
  5. 请求现在在 location /new 中处理。
  6. 规则3 匹配成功,将 URI 重写为 /another/test,并使用 last 标志。
  7. last 行为: 再次停止,用 /another/test 重新查找 location,假设没有匹配的 location,则返回 404。
  8. 最终结果: /another/test 对应的 404 页面。

场景2:请求 /new/test (直接访问)

  1. 请求直接进入 location /new
  2. 规则3 匹配成功,将 URI 重写为 /another/test,并使用 last 标志。
  3. last 行为: 停止,用 /another/test 重新查找 location,假设没有匹配的 location,则返回 404。
  4. 最终结果: /another/test 对应的 404 页面。

综合示例

示例1:URL 伪静态(SEO优化)

将动态的 index.php?id=123 格式转换为静态的 /article/123 格式。

nginx rewrite 参数
(图片来源网络,侵删)
server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    # 当请求是 /article/123 这样的格式时
    location /article/ {
        # 将 /article/123 重写为 /index.php?id=123
        # 使用 break,因为重写后 Nginx 会直接请求 /index.php 文件
        rewrite ^/article/(\d+)$ /index.php?id=$1 break;
    }
    # 处理所有对 /index.php 的请求
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

示例2:域名重定向(HTTP -> HTTPS & WWW)

http://example.comhttp://www.example.com 永久重定向到 https://www.example.com

server {
    listen 80;
    server_name example.com www.example.com;
    # 使用 permanent 返回 301 永久重定向
    # replacement 必须是完整的 URL
    rewrite ^(.*)$ https://www.example.com$1 permanent;
}
server {
    listen 443 ssl http2;
    server_name www.example.com;
    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;
    # ... 其他 SSL 和网站配置
}

示例3:访问控制

禁止特定 IP 访问网站,并返回 403。

server {
    listen 80;
    server_name example.com;
    # 如果客户端 IP 是 192.168.1.100
    if ($remote_addr = "192.168.1.100") {
        # 重写到一个不存在的路径,break,这样就会找不到文件返回 404
        # 或者直接返回 403
        return 403;
        # rewrite ^ /forbidden.html break; // 另一种方式
    }
    # ... 正常的网站配置
}

重要注意事项

  1. 正则表达式顺序: Nginx 按照配置文件中的顺序依次执行 rewrite 规则,直到匹配到一条带有 lastbreak 标志的规则,或者执行完所有规则。
  2. 性能影响: 过多的 rewrite 规则会增加 Nginx 的匹配开销,影响性能,应尽量避免使用过于复杂的正则表达式。
  3. 循环重定向: 使用 last 时要特别小心,如果重写后的 URI 经过 location 匹配后又回到了原始的 rewrite 规则,就会形成无限循环,Nginx 有一个内置的 max_redirects 限制(默认为10次),超过后会返回 500 错误。
  4. rewrite_log: rewrite 规则不生效,可以开启 rewrite_log 来调试。
    http {
        rewrite_log on; # 开启重写日志
        error_log /var/log/nginx/error.log notice; # 日志级别需要为 notice 或更详细
        # ...
    }

    日志中会显示 rewrite 的匹配和执行过程。

希望这份详细的解释能帮助你完全掌握 Nginx 的 rewrite 指令!

-- 展开阅读全文 --
头像
Acer E5-571G拆机教程,这些步骤你get了吗?
« 上一篇 01-14
envy 14 j104tx拆机步骤是怎样的?
下一篇 » 01-14

相关文章

取消
微信二维码
支付宝二维码

最近发表

标签列表

目录[+]