Nginx 中 rewrite 用于路径重写与重定向,return 用于快速响应或终止请求;rewrite 适合动态路径变换,return 更高效安全,适用于跳转、拦截、兜底等场景。

在 Nginx 中,rewrite 和 return 是两类不同但互补的 URL 处理指令:rewrite 用于重写或重定向请求路径,而 return 更轻量、更直接,适合快速响应或终止请求。合理搭配二者,能显著提升 URL 规范化的效率与可维护性,避免冗余匹配、循环跳转或逻辑混乱。
明确分工:什么情况用 rewrite,什么情况用 return
rewrite 适合需要路径变换、参数提取、多步逻辑或内部重写的场景;return 则适用于无需路径解析、只需立即响应的状态码返回(如 301/302 跳转、403 拒绝、404 统一兜底等)。
- 用 return 301 替代 rewrite ... permanent 实现域名或协议跳转——更高效、无正则开销、不触发 location 重匹配
- 当仅需拦截非法访问(如恶意爬虫、黑名单 UA、测试环境 IP)时,优先用 return 403 或 return 444,比 if + rewrite 更简洁安全
- 对已知固定路径的废弃接口(如 /api/v1/xxx),用 return 410 明确告知资源已永久删除,比 rewrite 到 404 页面更符合语义
用 return 实现“零正则”强制跳转
很多规范需求其实不需要正则匹配,比如 HTTP → HTTPS、www → 非 www、旧域名 → 新域名。此时 return 比 rewrite 更推荐:
-
HTTP 强制跳转 HTTPS:在 80 端口 server 块中直接写
return 301 https://$host$request_uri; -
统一主域名(去 www):
if ($host ~* ^www\.(.+)$) { return 301 https://$1$request_uri; } -
保留参数的域名迁移:
server_name old.com; return 301 https://new.com$request_uri;
这类写法不依赖正则捕获组,不触发 location 重匹配,性能更高,也更易读。
rewrite 专注路径转换,配合 return 做兜底与校验
rewrite 擅长处理动态路径映射(如 /p/123.html → /post?id=123),但它本身不阻止非法请求。建议用 return 补齐边界控制:
- 先用 if (!-e $request_filename) 判断静态文件不存在,再 rewrite 到入口脚本:
if (!-e $request_filename) { rewrite ^/(.*)$ /index.php?$1 last; } - 在 rewrite 后加 return 400 阻止非法参数:
if ($args ~ "script.*=.*") { return 400; } - 对敏感路径(如 /admin、/.git)直接 return 403:
location ~ ^/(admin|\.git|\.env) { return 403; }
避免常见陷阱:rewrite 与 return 的冲突点
二者混用时容易因执行顺序或作用域引发问题:
- return 在 if 块中会提前终止,rewrite 不再执行 —— 若需先判断再重写,确保 return 只出现在明确拦截逻辑里
- rewrite 的 last 标志会重启 location 匹配,可能绕过后续 return —— 如需绝对终止,改用 break 或将 return 放在更外层(如 server 级)
- 不要在同一个 location 中既用 rewrite permanent 又用 return 301 —— 功能重复,且后者优先级更高,易造成配置误解











