413 来自代理,不是应用
Nginx 拒绝请求体时,请求根本没到应用。应用日志为空,响应是 Nginx 的 HTML 错误页而不是 API 的 JSON。默认 client_max_body_size 是 1 MB,这解释了为什么小文件成功、大文件失败。
location /api/upload {
client_max_body_size 10m;
proxy_pass http://app;
proxy_request_buffering off;
}
把限制设在上传 location 上,而不是全局,以保护无关端点。如果前面还有 CDN 或 ingress,其限制也必须对齐。
对齐每一层
有效限制是请求路径中最小的那个。检查 ingress、Nginx、应用框架和对象存储策略。Nginx 允许 10 MB 而应用限制 5 MB 时,仍会在 5 MB 被拒绝,只是错误和日志来自另一层。
返回有用的错误
API 客户端需要可解析的响应。使用 error_page 413 = @json_413; 返回带 request id 的 JSON。不要返回客户端会误当 JSON 解析的通用 HTML 页面。记录拒绝时的内容长度和路由,但不要记录请求体。
保持限制安全
更大的上传限制会增加未认证滥用的暴露面。上传要求认证、限流、把大请求体流式写入磁盘,并在应用中再次校验大小。测试精确边界:刚好达到限制的文件应通过,多一个字节应以预期状态失败。
修复与验证
通过在上传 location 设置 client_max_body_size、对齐 ingress 和应用限制,并为 API 路由添加 JSON 错误页,修复有效限制。用刚好低于和刚好高于限制的文件验证,确认应用收到允许的请求,超大请求返回预期状态和内容类型。检查 Nginx 访问日志中的 request id,证明是哪一层拒绝的。