mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-09-02 14:53:46 +00:00
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:
@@ -730,6 +730,12 @@ svr.Post("/content_receiver",
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT` (default 1024) caps the number of
|
||||||
|
form-data parts only on the buffered path, where every part is accumulated into
|
||||||
|
`req.form`. The content receiver keeps nothing, so the cap does not apply here.
|
||||||
|
If your handler needs an upper bound on the number of parts, count them yourself
|
||||||
|
and return `false` from the callback to stop the parser.
|
||||||
|
|
||||||
### Send content with the content provider
|
### Send content with the content provider
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
|||||||
@@ -66,6 +66,38 @@ svr.Post("/upload",
|
|||||||
|
|
||||||
Only a small chunk sits in memory at any moment, so gigabyte-scale files are no problem.
|
Only a small chunk sits in memory at any moment, so gigabyte-scale files are no problem.
|
||||||
|
|
||||||
|
## Count the parts yourself
|
||||||
|
|
||||||
|
There is a cap on the number of parts, `CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT` (1024 by default), but it only applies to the buffered path, where every part is accumulated into `req.form`. The `ContentReader` keeps nothing on the library side, so the cap does not apply here.
|
||||||
|
|
||||||
|
If you want an upper bound, count the parts yourself and return `false` from the header callback. The parser stops right there.
|
||||||
|
|
||||||
|
```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; } // stop here
|
||||||
|
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");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
When `content_reader` returns `false`, set the response status yourself. The rest of the body is left unread and the connection is closed, so a client that is still sending sees the connection drop.
|
||||||
|
|
||||||
> **Warning:** When you use `HandlerWithContentReader`, `req.body` stays **empty**. Handle the body yourself inside the callbacks.
|
> **Warning:** When you use `HandlerWithContentReader`, `req.body` stays **empty**. Handle the body yourself inside the callbacks.
|
||||||
|
|
||||||
> For the client side of multipart uploads, see [C07. Upload a file as multipart form data](../c07-multipart-upload).
|
> For the client side of multipart uploads, see [C07. Upload a file as multipart form data](../c07-multipart-upload).
|
||||||
|
|||||||
@@ -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`は**空のまま**です。ボディはコールバック内で自分で処理してください。
|
> **Warning:** `HandlerWithContentReader`を使うと、`req.body`は**空のまま**です。ボディはコールバック内で自分で処理してください。
|
||||||
|
|
||||||
> クライアント側でマルチパートを送る方法は[C07. ファイルをマルチパートフォームとしてアップロードする](../c07-multipart-upload)を参照してください。
|
> クライアント側でマルチパートを送る方法は[C07. ファイルをマルチパートフォームとしてアップロードする](../c07-multipart-upload)を参照してください。
|
||||||
|
|||||||
Reference in New Issue
Block a user