请求体超限时 nginx 在什么时候回 413?client 还会不会把整个请求体发完?chunked 上传和流式转发会怎样?怎么按路径放宽?这篇用原始 socket 把几种情形量出来。
Content-Length | client 看到 | client 实际发出 | 耗时 | 上游收到的请求体 ---------------+-----------+-------------+--------+--------- 0.5 MB | 200 | 0.5 MB | 0.00 s | 0.50 MB 2 MB | 413 | 2.0 MB | 0.00 s | 没到上游 20 MB | 413 | 20.0 MB | 0.01 s | 没到上游 200 MB | 413 | 200.0 MB | 0.08 s | 没到上游 Content-Length 超限的请求,nginx 回 413 之后会“延迟关闭”(lingering close):继续把 client 还在发的请求体读掉丢弃一段时间,所以 client 大多还能收到 413;client 发得快、请求体特别大时,发送可能先于 413 的到达而失败(看 client 实际发出的字节数)
读请求体之前就回 413,但 client 仍会把请求体发完,nginx 延迟关闭并丢弃。
配置 | client 看到 | client 实际发出 | 上游收到的请求体 -------------------------------+-----------+-------------+--------- proxy_request_buffering on(默认) | 413 | 5.0 MB | 没到上游 proxy_request_buffering off | 413 | 5.0 MB | 1.05 MB chunked 没有事先声明长度,nginx 只能边读边数,读超过限制才知道超限:缓冲打开时请求体还没转给上游,上游完全不知情;关闭缓冲(边收边转)时,上游已经收到了一部分请求体,然后连接被掐断,上游看到的是残缺的请求
chunked 只能边读边数;关掉请求缓冲时,上游会收到一部分残缺的请求体。
请求体大小 | /api(1m) | /upload(50m) -------+----------+------------- 0.5 MB | 200 | 200 5 MB | 413 | 200 60 MB | 413 | 413 client | 看到 | client 实际发出的请求体 | 耗时 -----------------------+-----+-----------------+------- 不带 Expect | 413 | 5.0 MB | 0.00 s 带 Expect: 100-continue | 413 | 0.0 MB | 0.00 s
location 级的 client_max_body_size 可以覆盖;Expect: 100-continue 让 client 在超限时省下请求体。