Goal#
Expose HTTP response bodies as ReadableStream instances and accept ReadableStream request bodies in fetch(), replacing the current buffer-everything model in we-js/src/fetch.rs.
Depends on: "Implement Streams API foundation" and "Implement Streams API: pipeTo, pipeThrough, tee, and byte streams".
Scope#
Response.body- Returns a
ReadableStreamofUint8Arraychunks instead of being absent Response.bodyis locked once a reader is acquired or once a body-consuming method (text(),json(),arrayBuffer(),blob(),formData()) is calledResponse.bodyUsedgetter reflects lock/consumption stateResponseclone produces atee()of the body
- Returns a
- HTTP layer
- Plumb
Transfer-Encoding: chunkedandContent-Lengthframing inwe-netso chunks are surfaced to the JS side as they arrive, rather than buffered - A new internal
BodyChunkChannel(or similar) that the HTTP client uses to push chunks; the JS side wraps it in aReadableStreamunderlying source - Cancellation: cancelling the
ReadableStreamaborts the underlying HTTP request and closes the connection (or returns it to the pool if appropriate)
- Plumb
- Request bodies from streams
new Request(url, { body: readableStream, duplex: 'half' })fetch(url, { body: readableStream })- HTTP client reads the stream and writes via
Transfer-Encoding: chunked - Errors on the stream abort the request
Response.body.tee()works for caching one branch while parsing the other- Backpressure: if the JS reader is slow, the network read loop pauses (i.e. stops reading from the socket) until the stream consumer pulls more
Acceptance Criteria#
const reader = (await fetch(url)).body.getReader();yields chunks as the HTTP response arrives, not buffered to the end- A 10 MB response can be streamed and processed chunk-by-chunk with only modest memory use
- Cancelling the response body stream closes the underlying TCP connection (or returns it to the pool with the connection drained, never both)
fetch(url, { body: stream, method: 'POST' })uploads chunks as they are producedresponse.text()afterresponse.body.getReader()throwsTypeError(body locked)- Same-origin and CORS checks already in
fetch.rscontinue to apply - Unit and integration tests for: streaming download, streaming upload, body locking, tee on response body, cancellation propagating to the network layer
- Conventions
cargo fmt --all --checkcargo clippy --workspace -- -D warningscargo test --workspace