Document that the multipart part-count cap only applies to the buffered form path

CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT is enforced only in
Server::read_content(), where parts are accumulated into req.form. The
streaming ContentReader path keeps nothing and was never in scope, but
this was undocumented (GHSA-923p-8q8g-xcqj). Note the split in the README
and show how to bound the part count from inside a ContentReader handler.
This commit is contained in:
yhirose
2026-08-28 08:26:08 -04:00
parent 139f30e0f1
commit c7db3da982
3 changed files with 70 additions and 0 deletions

View File

@@ -66,6 +66,38 @@ svr.Post("/upload",
メモリには常に小さなチャンクしか載らないので、ギガバイト級のファイルでも扱えます。
## パート数は自分で数える
`CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT`デフォルト1024というパート数の上限がありますが、これが効くのは`req.form`にすべてのパートを溜め込むバッファリング側だけです。`ContentReader`はライブラリ側で何も溜め込まないので、この上限は適用されません。
パート数に上限をつけたいときは、自分で数えてヘッダーのコールバックから`false`を返してください。パースはその場で止まります。
```cpp
svr.Post("/upload",
[](const httplib::Request &req, httplib::Response &res,
const httplib::ContentReader &content_reader) {
size_t count = 0;
auto ok = content_reader(
[&](const httplib::FormData &file) {
if (++count > 100) { return false; } // ここで打ち切る
return true;
},
[&](const char *data, size_t len) {
return true;
});
if (!ok) {
res.status = httplib::StatusCode::BadRequest_400;
return;
}
res.set_content("ok", "text/plain");
});
```
`content_reader``false`を返したら、レスポンスのステータスは自分でセットしてください。ボディの残りは読まずに接続を閉じるので、送信中のクライアントには接続が切れたように見えます。
> **Warning:** `HandlerWithContentReader`を使うと、`req.body`は**空のまま**です。ボディはコールバック内で自分で処理してください。
> クライアント側でマルチパートを送る方法は[C07. ファイルをマルチパートフォームとしてアップロードする](../c07-multipart-upload)を参照してください。