“413 Request Entity Too Large” 的标准答案是改 client_max_body_size。这篇在本机用自己的 nginx 把默认值的边界、写在哪个位置才生效、0 的含义、分块上传的判断时机、API 的 JSON 413 以及“到底是不是 nginx 拒绝的”逐个测了一遍。
POST 1048576 字节:HTTP 200,upstream got 1048576 bytes;上游收到 1048576
POST 1048577 字节:HTTP 413,413 Request Entity Too Large;上游收到 (没有收到请求)
error.log: [error] *4 client intended to send too large body: 1048577 bytes, request: "POST / HTTP/1.1", host: "127.0.0.1:9780"
POST 1500000 字节:HTTP 413,413 Request Entity Too Large;上游收到 (没有收到请求)
error.log: [error] *5 client intended to send too large body: 1500000 bytes, request: "POST / HTTP/1.1", host: "127.0.0.1:9780"默认 1 MiB,边界精确到 1 字节;被拒时上游收不到请求。
POST 5000000 字节到 /api:HTTP 200;上游收到 5000000 POST 5000000 字节到 /upload:HTTP 413;上游收到 (没有收到请求) POST 20000 字节到 /tiny:HTTP 413;上游收到 (没有收到请求)
http / server / location 都可以,上传走哪个 location 就要在那里或上层写够。
client_max_body_size 0,POST 30000000 字节:HTTP 200;上游收到 30000000
1m 限制,POST 30000000 字节(Content-Length):HTTP 413,curl 耗时 0.000574 s;上游收到 (没有收到请求)
error.log: [error] *4 client intended to send too large body: 30000000 bytes, request: "POST /limit1m HTTP/1.1", host: "127.0.0.1:9780"
1m 限制,POST 30000000 字节(分块,没有 Content-Length):HTTP 413,curl 耗时 0.001413 s;curl 退出码 0;上游收到 (没有收到请求)
error.log: [error] *5 client intended to send too large chunked body: 983884+65524 bytes, request: "POST /limit1m HTTP/1.1", host: "127.0.0.1:9780"0 不检查;有 Content-Length 读完请求头就拒绝,分块则读到超过才拒绝。
POST 5000000 字节:HTTP 413,body = {"error":"payload too large","limit":"1m"}
Python urllib 一次发 5000000 字节:HTTP 413,body = {"error":"payload too large","limit":"1m"}error_page 413 指向一个 location,API 可返回 JSON。
nginx 允许 50m,上游应用读完请求体后自己拒绝:HTTP 413,页面 "upstream app says 413",error.log 里 0 条错误
nginx 自己拒绝有 too large body 日志;上游应用的 413 被透传,日志里没有错误。