Nginx 缓存 404 页面需拦截并改写为 200 后缓存:先定义专用缓存区,再通过 proxy_intercept_errors 和 error_page 拦截 404 并内部重定向至 @handle_404,最后在该 location 中返回可缓存的 200 响应(如静态 404.html),配合 proxy_cache_valid 200 10s 实现短时防刷。

Nginx 对错误页面(比如 404)做短期缓存,核心不是直接缓存 404 状态码本身——因为 proxy_cache_valid 404 1s 虽然语法合法,但默认情况下 Nginx 不缓存非 2xx/301/302 响应,除非你主动拦截并转换状态码。
所以真正可行的路径是:拦截后端返回的 404 → 改写为 200 → 再缓存这个 200 响应。这种方式既防刷又可控,也是生产环境推荐做法。
✅ 正确配置思路:拦截 + 重定向 + 缓存 200
你需要三部分协同:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
1. 定义专用缓存区(http 块内)
proxy_cache_path /var/cache/nginx/404_cache levels=1:2 keys_zone=404_cache:10m inactive=5m max_size=100m use_temp_path=off;
- 专用于错误页缓存,避免和主缓存混用
-
inactive=5m表示 5 分钟没被访问就自动清理,配合短周期更安全
2. 在 location 中启用拦截与内部重定向
location / {
proxy_pass http://backend;
proxy_intercept_errors on; # ⚠️ 必须开启,才能捕获 404
error_page 404 = @handle_404; # 拦截后交由内部 location 处理
}-
proxy_intercept_errors on是关键开关,否则error_page不生效 -
= @handle_404表示内部重定向且状态码改为 200(不是 302 跳转)
3. 在 @handle_404 中返回可缓存的 200 页面
location @handle_404 {
proxy_cache 404_cache;
proxy_cache_valid 200 10s; # 只对 200 生效 → 缓存 10 秒
proxy_cache_use_stale updating;
proxy_cache_lock on;
# 方式一:静态文件(最轻量,推荐)
root /usr/share/nginx/html;
try_files /404.html =404;
# 方式二:代理后端 HTML(需后端返回 200)
# proxy_pass http://static_backend/404.html;
# proxy_set_header Host $host;
}-
try_files /404.html =404:找不到/404.html就真返回 404(兜底) -
proxy_cache_valid 200 10s是实际起作用的缓存策略,10 秒足够防刷,又不会卡太久 -
proxy_cache_lock on防止并发请求重复回源,尤其适合突发 404 场景
? 验证是否生效
加一行响应头方便调试:
add_header X-Cache-Status $upstream_cache_status;
请求一个不存在路径,观察响应头:
- 第一次:
X-Cache-Status: MISS - 后续 10 秒内:
X-Cache-Status: HIT - 超过 10 秒后首次:
X-Cache-Status: UPDATING(锁住时)或MISS
⚠️ 注意事项
- 不要依赖
proxy_cache_valid 404 1s单独生效——它只在 Nginx 自己生成 404(如return 404)时才可能缓存,对proxy_pass返回的 404 默认不缓存 - 若后端返回的是带 body 的 404(如 JSON 错误),也可用
sub_filter替换内容+改状态码,但复杂度高,静态页方案更稳 - 确保
/var/cache/nginx/404_cache目录存在且 Nginx 进程有读写权限
不复杂但容易忽略

















