2.6 KiB
marshal-response
(no submodules)
Purpose
This module is the response-side counterpart to marshal-request. It
converts a Fetch Response produced by a worker-side handler into a
plain SerializedResponse envelope safe to ship across a MessagePort,
and rehydrates that envelope back into a real Response on the main
process so the host pipeline can apply Steps 9-11 (response validation,
ETag, Server-Timing aggregation).
Features
- Validates status code is in the 100-599 range (
ROUTER_BRIDGE.RESPONSE_INVALID). - Preserves status text and full header list (response headers are not on any deny-list — the bridge only filters request-side credentials).
- Inlines bodies up to
DEFAULT_RESPONSE_INLINE_LIMIT(64 KiB) and streams everything else through the streaming module. - Hard cap at
DEFAULT_RESPONSE_MAX_BYTES(16 MiB) for inline bodies; oversize payloads either stream or fail withROUTER_BRIDGE.BODY_TOO_LARGE. - Tagged-union body shape mirrors the request side for symmetry.
Usage: Basic
import { marshalResponse, rehydrateResponse } from
"@suaveplan/api-router-worker-bridge/marshal-response";
const wire = await marshalResponse(
new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { "content-type": "application/json" },
})
);
const reborn = rehydrateResponse(wire);
await reborn.json(); // { ok: true }
Usage: Advanced
Stream a large attachment response via a stream id:
import {
marshalResponse,
rehydrateResponse,
} from "@suaveplan/api-router-worker-bridge/marshal-response";
const streamId = 99;
const wire = await marshalResponse(largeDownload, {
streamId,
inlineBodyLimit: 0,
});
// caller pipes `largeDownload.body` over the streaming channel; main side:
const reborn = rehydrateResponse(wire, mainStreamFor(streamId));
API Reference
marshalResponse(response, options?) → Promise<SerializedResponse>.rehydrateResponse(serialized, streamBody?) → Response.serializedResponseSchema— Zod validator.DEFAULT_RESPONSE_INLINE_LIMIT,DEFAULT_RESPONSE_MAX_BYTES.
Implementation Notes
statusText is preserved because some clients (and HTTP/1.1 caches)
still depend on the reason phrase. The body tagged union is identical in
shape to SerializedRequestBody, but the two types are intentionally
distinct so future divergence (e.g. server-sent-event hints) does not
silently propagate. Status validation runs first so a 100/600 test
case fails cleanly even when the body would also fail.