コンテンツにスキップ

大きなボディのストリーミング

body_out より大きなレスポンスボディは、複数のラウンドに分けて作ります。 このページのサーバーは 1 MiB のボディを返し、クライアントがその長さと SHA-256 を出力します。

コード

main.c
#define WIRED_MAIN
#include "wired.h"
#define BODY_SIZE (1024 * 1024)
/* A body bigger than body_out goes out over several rounds: each call fills
* what fits starting at offset and sets *more until the whole body is sent.
* Byte i of the body is (u8)i. */
static int on_request(
void* ctx,
const wired_h3reqdrive_req* req,
u64 offset,
wired_obuf* body_out,
const char** content_type,
int* more,
u64* total_size) {
(void)ctx;
(void)req;
u64 n = BODY_SIZE - offset;
if (n > body_out->cap) n = body_out->cap;
for (u64 i = 0; i < n; i++) body_out->p[i] = (u8)(offset + i);
body_out->len = n;
*more = offset + n < BODY_SIZE;
*total_size = BODY_SIZE;
*content_type = "application/octet-stream";
return 1;
}
int wired_main(int argc, char** argv) {
/* Fixed demo identity (self-signed certificate; never for production). */
static wired_srvboot_demo_keys keys;
wired_srvboot_id id;
wired_srvboot_demo(&id, &keys, 0x50, "guide-h3");
u16 port = (u16)wired_cliargs_int(argc, argv, "--port", 4433);
wired_srvrun_handler h = {.cb = on_request};
wired_srvrun_obs obs = {0};
return wired_server_run(port, &id, h, obs) ? 0 : 1;
}

実行結果

Terminal window
$ ./h3-streaming --port 4433
conn closed by peer (CONNECTION_CLOSE)
Terminal window
$ probe h3get 127.0.0.1:4433 /big
GET /big status=200 content-type=application/octet-stream bytes=1048576 sha256=fbbab289f7f94b25736c58be46a994c441fd02552cc6022352e3d86d2fab7c83
  • ハンドラーが *more = 1 を設定しているあいだ、同じリクエストに対して繰り返し呼ばれます。 offset は、送信済みのボディのバイト数です。
  • 各ラウンドでは、offset の位置から最大 body_out->cap バイトを書きます。
  • *total_size でボディ全体の長さを先に伝えると、ボディ全体がそろう前にレスポンスでその長さを知らせられます。 この値は最初のラウンドでだけ読まれます。