nginx 自定义 http 状态码返回主要通过 return 指令直接响应或 error_page 捕获重写,两者均无需后端参与;return 适用于静态判断场景,支持 100–999 状态码并可附带响应体;map 指令更安全高效地实现变量驱动的状态码映射;error_page 需配合 proxy_intercept_errors 等指令捕获原始错误码并重写;api 场景下需用命名 location 返回 json 响应。

Nginx 配置基础的自定义 HTTP 状态码返回,核心是用 return 指令直接响应,或用 error_page 捕获并重写,两者适用场景不同,但都无需后端参与,纯由 Nginx 在响应阶段控制。
用 return 直接返回指定状态码
这是最简单、最常用的方式,适合基于请求路径、参数或头信息做静态判断的场景。 - `return` 必须写在 `server`、`location` 或(不推荐)`if` 块中 - 支持 100–999 范围内的任意数值,包括非标准码(如 451、499、521) - 可选附带响应体和自动设置 Content-Type例如,禁止访问某个目录时返回 403:
location /admin/ {return 403 "Access forbidden to this area.";}
又如,对特定地区请求返回法律限制状态码 451:
location /content/ {if ($http_x_forwarded_for ~ "192\.168\.10\.") {
return 451 "Unavailable in your jurisdiction.";
}
} ⚠️ 注意:`if` 在 location 中慎用;更推荐用 `map` 实现条件映射(见下文)。
用 map 实现变量驱动的状态码
当需要根据请求头、Cookie、参数等动态决定状态码时,`map` 比 `if` 更安全、高效,且在 rewrite 阶段前完成计算。步骤如下:
- 在 `http` 块中定义映射变量,如 `$custom_status`
- 用字符串、正则或默认值匹配输入变量(如 `$http_user_agent`、`$arg_v`)
- 在 `location` 中用 `return $custom_status` 触发响应
示例:根据请求头 `X-Env` 返回不同状态码
default 200;
"staging" 406;
"blocked" 451;
}
server {
location /api/ {
return $custom_status;
}
}
用 error_page 拦截并重写已有错误码
它不改变业务逻辑,只接管 Nginx 或后端返回的原始状态码,再以新状态或页面响应。关键点:
- 必须配合 `proxy_intercept_errors on`(反向代理)或 `fastcgi_intercept_errors on`(PHP)才能捕获后端错误
- `error_page 404 =200 /fallback.html` 表示将 404 捕获后以 200 状态返回 fallback 页面
- 加 `=` 表示重写响应状态码;不加则保持原码,仅跳转到指定 URI
- 目标路径需由 `location = /xxx` 承接,并加 `internal` 防止用户直访
常见写法:
error_page 404 /404.html;location = /404.html {
root /usr/share/nginx/html;
internal;
}
返回 JSON 类型的自定义错误响应
API 场景下常需结构化错误体,比如限流返回 429 + JSON。Nginx 命名 location 是唯一支持 `return` 带 body 的合法位置。配置要点:
- 先用 `limit_req_status 429` 触发自定义限流码(需 Nginx ≥ 1.3.15)
- 用 `error_page 429 = @rate_limited` 将响应交由命名 location 处理
- 在 `location @rate_limited` 中用 `return` 输出 JSON,并设 `Content-Type`
示例:
limit_req_status 429;error_page 429 = @rate_limited;
location @rate_limited {
add_header Content-Type "application/json";
return 429 '{"code":429,"message":"Too many requests","retry_after":60}';
}
不复杂但容易忽略











