400错误主因是Nginx的client_header_buffer_size默认1KB过小,无法容纳超长Cookie单行;需协同调大large_client_header_buffers(如4 16k)并源头精简Cookie。

遇到“400 Bad Request: Request Header Or Cookie Too Large”错误,大概率不是后端代码问题,而是 Nginx 在请求头解析阶段就拒绝了连接——根本原因在于 client_header_buffer_size 默认值太小(通常仅 1KB),无法容纳超长 Cookie 行。但只调大它远远不够,必须理解它和 large_client_header_buffers 的协同机制。
它不是“最大限制”,而是“第一道缓冲门”
client_header_buffer_size 定义的是 Nginx 为每个请求分配的初始请求头缓冲区大小,用于存放请求行(如 GET /path HTTP/1.1)和前几行请求头(Host、User-Agent、Cookie 等)。关键点在于:
- 它针对的是单行请求头字段:整条
Cookie: a=b; c=d; ...必须能完整放进这个缓冲区,否则直接报 400; - 它不控制整个请求头总长度,也不允许跨缓冲拼接;
- 默认 1KB 对现代含 JWT、多埋点 ID、SSO 上下文的 Cookie 来说,几乎必然不足。
真正兜底的是 large_client_header_buffers
当某一行(比如 Cookie)超出 client_header_buffer_size,Nginx 不会报错,而是尝试启用 large_client_header_buffers 分配一个更大的缓冲区来承接这一行。但前提是:
-
large_client_header_buffers中每个缓冲区的大小,必须大于等于该超长行的实际字节数; - 该行仍需完整装入单个 large buffer 中(不能拆成两段);
- 如果 large buffer 单个容量仍不够,或数量用尽,就返回 400。
例如:large_client_header_buffers 4 16k 表示最多可分配 4 个缓冲区,每个最大 16KB——这意味着单行最长可支持约 16KB(实际略小,含换行符等开销)。
怎么配才合理又安全
盲目设成 64k 或 128k 不但浪费内存,还可能被用于慢速攻击。推荐分步操作:
- 打开浏览器开发者工具 → Network → 找一个失败请求 → Headers → 复制 Cookie 值 → 粘贴到编辑器里查字节数(ASCII 编码,1 字符 ≈ 1 字节);
- 实测常见最大值若为 3200 字节,建议
client_header_buffer_size 4k(略大于 P99); - 同步设置
large_client_header_buffers 4 16k,确保单行上限覆盖峰值(如 SSR 页面带用户画像 JSON 可达 12KB+); - 配置放在
http块(全局)或server块(精准控制某域名),避免在location中覆盖。
比调参更关键的源头治理
加缓冲只是应急手段,长期应减少 Cookie 膨胀:
- JWT、Token 原文别直接塞 Cookie,改用服务端 session + 短 ID;
- 前端埋点 SDK 产生的冗余 Cookie(如
_ga、amplitude_id)做子域隔离或定期清理; - 避免多个子域重复写入相似 Cookie,合并 domain 或精简 scope;
- 后端响应时检查
Set-Cookie总长,对超长值主动截断或拒绝下发。
验证是否生效:用 curl -H "Cookie: $(python3 -c 'print(\"a=\" + \"x\"*5000)')" https://yoursite.com/ 模拟请求,确认返回 200,并检查 error.log 不再出现 too large header 记录。


















