Skip to content

Streaming bodies

Read large inbound bodies chunk by chunk and return AsyncIterable responses without buffering the full payload.

AI generated, pending review Updated 10 days ago · Flare 0.3

You’re moving a payload too big to hold in memory all at once. Stream the inbound body with a stream contract marker, and stream the outbound body by returning an AsyncIterable.

Declare body: stream on the route descriptor. Import stream from @flare-ts/core.

import { FlareHost, FlareResponse, stream } from "@flare-ts/core";
import { node } from "@flare-ts/core/node";
const host = new FlareHost(node);
host.http.post("/upload", { body: stream }, async (ctx) => {
let bytes = 0;
for await (const chunk of ctx.req.stream()) {
bytes += chunk.byteLength;
}
return new FlareResponse(200, { bytes });
});
const app = host.build();
app.run();

Or read the same iterable from scope.input.body on inline routes:

host.http.post("/upload", { body: stream }, async (_ctx, scope) => {
let bytes = 0;
for await (const chunk of scope.input.body) {
bytes += chunk.byteLength;
}
return new FlareResponse(200, { bytes });
});

The stream attaches before before middleware, so before hooks can read it too.

Raise the cap with maxBodyBytes on the descriptor. See Request limits and bodies.

Return an AsyncIterable from the handler:

import { FlareHost } from "@flare-ts/core";
import { node } from "@flare-ts/core/node";
const host = new FlareHost(node);
host.http.get("/export", () => {
return (async function* () {
for (let i = 0; i < 1000; i++) {
yield `row ${i}\n`;
}
})();
});
const app = host.build();
app.run();

Each chunk is coerced to bytes: Uint8Array as-is, string UTF-8 encoded, anything else JSON.stringify’d then encoded.

For explicit headers, wrap a byte stream: new FlareResponse(200, byteIterable, { headers: { … } }). That constructor takes AsyncIterable<Uint8Array> and does not coerce chunks, so encode strings yourself; the coercion above applies only when you return the iterable directly.

import { FlareHost, stream } from "@flare-ts/core";
import { node } from "@flare-ts/core/node";
const host = new FlareHost(node);
host.http.post("/transform", { body: stream }, (ctx) => {
return (async function* () {
for await (const chunk of ctx.req.stream()) {
yield chunk;
}
})();
});
const app = host.build();
app.run();