405错误需主动拦截OPTIONS请求而非依赖error_page。应在location中用if判断$request_method='OPTIONS',配合add_header设置CORS头并return跳转至提示页或接口,因error_page对405无效且不触发拦截链路。

OPTIONS 请求返回错误(比如 405)时,不能靠 error_page 自动捕获并重定向——因为 405 是 Nginx 主动拒绝的响应,它发生在请求处理早期,error_page 默认不拦截这类“方法不被允许”的错误。真正可靠的做法,是在 location 块中**主动识别 OPTIONS 方法,并用 return 强制接管响应**,跳转到你指定的友好提示接口。
直接拦截并重定向 OPTIONS 请求
在对应 API 或静态资源的 location 块中,加一段明确判断 $request_method 的逻辑:
- 用
if ($request_method = 'OPTIONS')匹配预检请求 - 配合
return 302 /api-help?status=405跳转到你自己的提示页或接口 - 必须加
add_header补全 CORS 头,否则浏览器可能因缺少响应头而报错
示例配置:
location /api/ {proxy_pass http://backend;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://your-frontend.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
return 302 /notice/options-rejected;
}
}
为什么不用 error_page 处理 OPTIONS 错误
error_page 405 在绝大多数 Nginx 版本中是无效的,因为 405 不是由后端返回、也不是 Nginx 后期生成的错误,而是由 limit_except 或模块逻辑直接拒绝时立即返回的。它不经过 error_page 的拦截链路。试图写 error_page 405 = @options_help 通常不会触发。
更稳妥的替代方案:统一放行 OPTIONS 并跳转
如果你不需要真正处理预检,只希望所有 OPTIONS 都导向提示页,可关闭方法限制,再统一跳转:
- 移除或放宽
limit_except配置(如删掉deny all) - 在 location 顶层加 if 判断,不管路径如何,只要 method 是 OPTIONS 就跳转
- 跳转目标可以是 HTML 页面,也可以是返回 JSON 提示的后端接口,例如:
return 302 /api/error?code=405&msg=Invalid%20method;
注意事项
跳转后的目标接口(如 /notice/options-rejected)需确保:
- 该路径有对应 location 定义,且能正常响应(比如指向静态文件或 proxy_pass 到后端)
- 若目标是静态 HTML,记得在对应 location 中加
internal;防止用户绕过跳转直接访问 - 避免循环:不要让跳转目标本身又触发 OPTIONS 判断,否则会 302 套娃











