nginx中error_page本身不触发浏览器跳转,仅作内部重写;要实现真实跳转(301/302),需配合命名location与return或rewrite指令。基础用法为返回静态404页(url不变),须在server块配置error_page 404 /404.html、location = /404.html指定root并加internal;反向代理场景必须启用proxy_intercept_errors on;等号“=”决定状态码:无等号返回404,=返回200,=301或无等号外链则触发对应跳转。

在 Nginx 中,error_page 本身不直接做浏览器跳转(301/302),而是内部重写;要实现真正的“跳转”,得靠它配合命名 location 和 return 302 或 rewrite ... redirect。
基础用法:返回静态错误页(地址栏不变)
这是最常用也最容易配错的场景。比如显示一个友好的 404 页面:
-
error_page 404 /404.html;必须放在server块里(不能只写在某个子location内,除非你只想对该路径生效) - 必须配一个
location = /404.html块,里面指定root(不是完整路径,是目录前缀),且确保文件真实存在、Nginx 进程有读权限 - 加
internal;是推荐做法,防止用户手动访问/404.html - 如果后端是反向代理(如 proxy_pass),还得在同级
location加proxy_intercept_errors on;,否则后端返回的 404 不会被拦截
进阶用法:真正跳转到搜索页或外部 URL
想让访问 /abc 不存在时,浏览器跳到 /search?q=abc,就得走命名 location + 重定向:
- 用
error_page 404 @to_search;把错误转发给命名 location - 在
location @to_search里用set提取原始路径(如$uri),必要时清洗(去掉开头斜杠) - 执行
return 302 /search?q=$search_query;—— 这才是客户端可见的跳转,地址栏会变,状态码是 302 - 注意:不能在命名 location 里用
proxy_pass后再指望自动继承请求头,需显式传递(如proxy_set_header)
关键细节:等号(=)的作用别搞混
error_page 后面加不加等号,结果完全不同:
-
error_page 404 /404.html;→ 返回 404 状态码,内容是/404.html的 HTML -
error_page 404 = /404.html;→ 返回 200 状态码,内容仍是/404.html(适合 SEO 隐藏错误) -
error_page 404 =301 https://example.com/notfound;→ 返回 301 跳转,浏览器跳到目标 URL -
error_page 404 http://xxx.com/404.html;→ 返回 302 临时跳转(不加等号默认就是 302)
常见踩坑点
很多配置看似正确却没生效,往往卡在这几个地方:
-
location = /404.html的root路径拼出来找不到文件,或者权限不对(检查ls -l和stat) - 用了
alias而不是root,尤其对=匹配的 location,alias容易少一层路径 - 反向代理场景下漏了
proxy_intercept_errors on;,导致后端返回的 404 直接透传 - 把
error_page写在location /api里,结果主站 404 还是默认页 - 想用
if判断 Referer 再跳转,但error_page触发后不进入普通location,if失效,得在命名 location 里处理











