本文档基于 Rewrite.html 文件内容进行总结,并在此基础上进行了深度拓展,补充了 Nginx Rewrite 模块的核心概念、最佳实践及相关高级用法。
1. 原文档知识点总结
1.1 Rewrite 概述
- 定义: Rewrite 主要用于实现 URL 地址重写和重定向,将请求映射到新的 URL。
- 核心指令:
rewrite regex replacement [flag] - 作用域:
server,location,if
1.2 应用场景
- 地址跳转: 域名变更(如
www.lzy.com->mobile.lzy.com)。 - 协议跳转: 强制 HTTP 转 HTTPS。
- 伪静态: 将动态 URL(如
?id=1)转化为静态形式(如/1.html),利于 SEO 和安全性。 - SEO 优化: 缩短 URL 层级,使其更易被搜索引擎收录。
1.3 Flag 标记详解
| 标记 (Flag) | 说明 | 场景建议 |
| :--- | :--- | :--- |
| last | 停止当前 Rewrite 匹配,重新发起新一轮 Location 匹配 | 用于 Server 或 Location 区块,适用于重写后需要进一步处理的 URL |
| break | 停止当前 Rewrite 匹配,不再匹配后续规则 | 用于 Location 区块,通常用于文件路径重写,防止循环重定向 |
| redirect | 返回 302 临时重定向 | 临时维护、短链跳转(浏览器不缓存) |
| permanent | 返回 301 永久重定向 | 域名迁移、协议升级(浏览器会缓存,SEO 权重转移) |
1.4 实战案例回顾
- 路径重写:
/abc/1.html->/ccc/bbb/2.html - 参数提取:
/2018/ccc/2.html->/2014/ccc/bbb/2.html(利用正则分组$1) - 全站跳转:
/test->https://www.oldboy.com - HTTPS 强制跳转: 利用
rewrite ^(.*) https://$server_name$1 redirect - 条件判断: 利用
if指令结合$remote_addr实现 IP 访问控制(如维护页面)。
2. 知识点深度拓展
2.1 正则表达式 (Regular Expressions) 基础
Nginx 使用 PCRE (Perl Compatible Regular Expressions) 语法。熟练掌握正则对于编写 Rewrite 规则至关重要。
| 符号 | 含义 | 示例 |
| :--- | :--- | :--- |
| ^ | 匹配字符串的开始 | ^/admin 匹配以 /admin 开头的路径 |
| $ | 匹配字符串的结束 | .html$ 匹配以 .html 结尾的路径 |
| . | 匹配除换行符以外的任意字符 | .* 匹配任意字符序列 |
| * | 重复 0 次或多次 | |
| + | 重复 1 次或多次 | |
| ? | 重复 0 次或 1 次 | |
| () | 分组捕获,用于 $1, $2 变量提取 | ^/blog/(.*)$ 中 $1 获取博客 ID |
| \ | 转义字符 | \.html 匹配实际的点号 |
| [] | 字符集合 | [a-z] 匹配任意小写字母 |
2.2 last vs break 的底层区别
这是 Nginx Rewrite 中最容易混淆的点:
-
last: 相当于 Apache 的[L]标记。修改 URI 后,Nginx 会重启请求处理流程,根据新的 URI 重新匹配location。如果配置不当,容易造成死循环(Nginx 会在 10 次循环后返回 500 错误)。 -
break: 修改 URI 后,继续在当前location中执行后续指令(如proxy_pass或直接读取文件),不再跳出当前location去寻找新的匹配。
最佳实践:
- 在
server上下文中,通常使用last(或者默认行为其实就是类似last)。 - 在
location上下文中,如果你只是想修改文件路径并直接响应,用break。如果你想把请求转给另一个location处理(比如 PHP-FPM),用last。
2.3 性能优化:rewrite vs return vs try_files
虽然 rewrite 很强大,但它是计算密集型的(需要正则引擎)。
- 推荐使用
return进行重定向:
如果你只是想做简单的 301/302 跳转,return 比 rewrite 更高效,因为它不需要解析正则。
```nginx
# 不推荐
rewrite ^(.*)$ https://www.example.com$1 permanent;
# 推荐 (性能更好,可读性更强)
return 301 https://www.example.com$request_uri;
```
- 推荐使用
try_files处理伪静态:
对于现代框架(Laravel, Django, ThinkPHP 等),通常不需要写复杂的正则,而是使用 try_files。
```nginx
# 将所有不存在的文件请求转发给 index.php
location / {
try_files $uri $uri/ /index.php?$query_string;
}
```
这比 rewrite ^/(.*)$ /index.php?s=$1 last; 更直观且性能略好。
2.4 常用 Nginx 内置变量补充
除了原文档列出的变量,以下变量在 Rewrite 和日志中也非常有用:
-
$request_time: 请求处理时间(单位秒,精确到毫秒),用于性能分析。 -
$upstream_response_time: 后端服务(如 PHP-FPM, Tomcat)响应时间。 -
$http_referer: 来源页面,常用于防盗链配置。
```nginx
valid_referers none blocked server_names *.example.com;
if ($invalid_referer) {
return 403;
}
```
-
$http_user_agent: 客户端浏览器标识,常用于屏蔽爬虫或针对移动端跳转。
```nginx
if ($http_user_agent ~* (Scrapy|Curl|HttpClient)) {
return 403;
}
```
2.5 调试技巧
在复杂的 Rewrite 规则调试中,除了开启 rewrite_log on;,还可以使用 add_header 输出变量值到响应头,方便在浏览器或 Postman 中查看(注意:add_header 在 301/302 跳转时可能不显示)。
location /test {
set $my_var "123";
# 调试显示变量值
add_header X-Debug-Var $my_var;
add_header X-Debug-Uri $uri;
}
3. 总结
Nginx 的 Rewrite 模块是流量控制的瑞士军刀。虽然正则功能强大,但在实际生产环境中,应遵循 "简单至上" 的原则:能用 return 解决的不用 rewrite,能用 try_files 解决的不用正则。合理使用 Flag 和内置变量,可以构建出高效、安全且易于维护的 Web 服务器配置。
Comments NOTHING