Nginx HTTP代理不直接重写请求,而是通过rewrite+proxy_pass组合实现路径改写与代理;rewrite修改请求路径,proxy_pass转发改写后请求,return/deny/if/location控制拦截与跳转;常用场景包括API路径标准化、前端路由代理、防盗链、SPA回退及HTTP→HTTPS强制跳转。

Nginx 中 HTTP 代理本身不直接“重写请求”,而是通过 rewrite(重写) + proxy_pass(代理)的组合,或配合 location、if、return 等指令实现路径改写、跳转、拦截等行为。关键在于分清:
-
rewrite改的是请求路径(内部重写或客户端跳转); -
proxy_pass做的是把改完后的请求发给后端; - 拦截靠的是
return、deny、if判断或 location 匹配控制流向。
路径重写后再代理(最常用)
适用于统一 API 入口、前端路由代理、后端路径标准化等场景。
比如把 /api/v1/users 改成 /v1/users 再转发给后端服务:
location /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://backend;
proxy_set_header Host $host;
}-
rewrite ... break:仅在当前 location 内生效,改完路径后立刻执行proxy_pass,不重新匹配 location; -
proxy_pass末尾不加/→ 发送完整路径/api/v1/users; -
proxy_pass末尾加/→ 自动剥离/api/,发送/v1/users(推荐); - 不要用
last,否则可能触发循环匹配(尤其当后端也走/location 时)。
主动拦截非法或敏感请求
不转发、不查文件,直接响应控制:
# 禁止访问配置类资源
location ~* \.(env|ini|conf|yml|json)$ {
return 403;
}
# 拦截特定路径前缀
location /admin/ {
deny 192.168.10.5;
allow 192.168.10.0/24;
allow 127.0.0.1;
deny all;
}
# 防盗链(只允许自家域名引用静态资源)
location ~* \.(jpg|png|gif)$ {
valid_referers server_names *.example.com;
if ($invalid_referer) {
return 403;
}
}-
return 403比deny all更明确,且可搭配日志记录; -
valid_referers+$invalid_referer是防盗链标准做法; -
deny/allow顺序必须严格:先列具体拒绝项,再放行大范围,最后deny all收底。
基于条件做重定向或兜底路由
常见于单页应用(SPA)或旧链接迁移:
# 文件不存在时,全部回退到 index.html(支持前端路由)
location / {
try_files $uri $uri/ /index.html;
}
# 或用 if + rewrite 实现(注意 if 在 location 外慎用)
if (!-e $request_filename) {
rewrite ^(.*)$ /index.html break;
}
# 将旧文章路径永久跳转到新地址
rewrite ^/blog/(\d+)\.html$ /articles/$1 permanent;-
try_files是更推荐的方式,性能好、逻辑清晰; -
if在 location 块内可用,但避免在 server 级别滥用(Nginx 官方不建议); -
permanent=301,适合 SEO 迁移;临时跳转用redirect(302)。
HTTP → HTTPS 强制跳转与域名归一化
属于客户端重定向,不涉及代理,但常与代理共存:
# 所有 HTTP 请求跳 HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# 移除 www(HTTPS 下)
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate ...;
ssl_certificate_key ...;
return 301 https://example.com$request_uri;
}-
return 301比rewrite ... permanent更高效,无正则开销; -
$request_uri保留原始路径和查询参数,确保/a?b=1→/a?b=1; - 不要混用多个
return或嵌套if,容易导致跳转链或循环。
不复杂但容易忽略细节。


















