在 nginx 中,`rewrite` 指令用于修改 uri 路径,而 `error_page` 用于捕获和处理 http 错误状态码。要让两者配合工作,核心在于理解 nginx 的处理阶段:`rewrite` 发生在请求处理的早期(uri 重写阶段),而 `error_page` 通常作用于响应生成阶段或内部重定向。如果 `rewrite` 成功将请求指向了正确的资源,服务器返回正常状态码(如 200),则不会触发 `error_page`;只有当请求处理过程中产生错误(如 404、500)时,`error_page` 才会介入。因此,配合的关键在于:通过 `rewrite` 调整请求路径以匹配实际资源,若路径调整后仍找不到资源导致 404,则由 `error_page` 统一处理;或者利用 `error_page` 的 `=` 语法强制指定状态码,结合 `rewrite` 实现复杂的跳转逻辑。

如何配置 rewrite 与 error_page 处理 404 错误
要配合处理 404 错误,通常的做法是先用 `rewrite` 尝试修正 URL 结构,如果修正后依然无法找到文件,Nginx 会返回 404,此时由 `error_page` 捕获并跳转到自定义页面或执行另一个内部重定向。例如,将 `/old/path/` 下的请求重写为 `/new/path/`,若新路径不存在,则显示维护页面。

server {
listen 80;
server_name example.com;
# 定义 404 错误页
error_page 404 /maintenance.html;
# 将 /api/ 开头的请求重写为 /v1/api/
rewrite ^/api/(.*)$ /v1/api/$1 last;
location / {
root /var/www/html;
index index.html;
}
location /v1/api/ {
# 假设这里可能返回 404
try_files $uri $uri/ =404;
}
location = /maintenance.html {
internal;
root /var/www/errors;
}
}
在上述配置中,访问 /api/test 会被 rewrite 转换为 /v1/api/test。如果 /var/www/html/v1/api/test 存在,则直接返回内容;如果不存在,try_files 触发 =404,进而被 error_page 404 捕获,内部重定向到 /maintenance.html。注意 internal 指令确保 /maintenance.html 只能通过内部重定向访问,防止外部直接请求。
如何利用 error_page 的状态码参数配合 rewrite 进行跳转
除了处理 404,还可以利用 error_page 的第二个参数来改变返回给客户端的状态码,并结合 rewrite 实现 SEO 友好的跳转或业务逻辑路由。例如,当某个旧接口返回 410 Gone 时,可以将其重定向到新接口,并返回 301 永久移动状态码。这通常用于迁移 API 版本。

server {
listen 80;
server_name api.example.com;
# 当遇到 410 错误时,内部重定向到 /new-api/,并返回 301
error_page 410 =301 /new-api/;
location /old-api/ {
# 模拟旧接口返回 410
return 410;
}
location /new-api/ {
# 新接口的处理逻辑
proxy_pass http://backend_new;
}
}
在这个例子中,客户端请求 /old-api/something,Nginx 直接返回 410。由于配置了 error_page 410 =301 /new-api/,Nginx 会将请求内部重定向到 /new-api/,并将最终返回给客户端的状态码改为 301,同时 Location 头指向 /new-api/。这种组合常用于需要彻底废弃旧路径并引导用户到新路径的场景。需要注意的是,error_page 中的 =301 覆盖了默认的 410 状态码,使得客户端浏览器能正确执行重定向。
rewrite 中的 last 和 break 对 error_page 的影响是什么
在 rewrite 指令中,last 和 break 标志会影响后续的处理流程,从而间接影响 error_page 的触发时机。last 表示停止当前阶段的匹配,重新开始新一轮的 URI 查找,这意味着可能会进入新的 location 块,如果新 location 中再次发生错误,error_page 会根据新上下文生效。而 break 表示停止处理 rewrite 指令集,并使用当前的 URI 继续在当前 location 中处理,如 try_files 或静态文件服务。如果 break 后的操作失败,error_page 会在当前 location 上下文中触发。因此,选择 last 还是 break 决定了错误是在哪个 location 块中被捕获和处理。


















