HttpResponse::streamingFromIterable() for non-buffering consumption or HttpResponse::bufferedFromIterable() when replay is explicitly required. Passing a raw iterable to HttpResponse is rejected so it cannot silently retain every chunk.
Enabling Streaming
To receive a streaming response, set thestream option on the request:
withStreaming():
Consuming the Stream
Once you have a streaming request, callstream() on the pending response. This returns a PHP Generator that yields string chunks:
streamChunkSize setting in HttpClientConfig (default: 16384 bytes), which is an upper bound rather than a target: chunks are yielded as soon as the transport delivers them, so a chunk is usually far smaller than the limit and lowering the limit does not make data arrive sooner. Do not depend on chunk boundaries — parse the stream, not the framing.
Note: You do not need to explicitly setstream => trueon the request when usingPendingHttpResponse::stream(). The pending response will force streaming mode automatically. However, setting it on the request is useful when middleware needs to know the intended mode before execution.
Streaming LLM Responses
Streaming is essential for AI/LLM integrations where responses are generated token by token. Here is a typical pattern for streaming a chat completion:data: {...}\n\n). To parse these into clean payloads, use the EventSourceMiddleware.
Server-Sent Events with EventSourceMiddleware
TheEventSourceMiddleware handles the SSE protocol for you. It strips the data: prefixes, buffers partial lines, and yields complete event payloads. A final event is emitted when the source ends even if it has no trailing blank line. The parser buffer is limited to 1 MiB by default; configure maxBufferBytes on EventSourceMiddleware for a smaller or larger protocol-specific limit:
data: line and returns the value to yield. Return false to skip an event. This is useful for filtering out [DONE] markers or parsing JSON:
Downloading Large Files
Streaming is the right approach for downloading large files without exhausting memory:Capturing stream contents for inspection
Streamed bodies are consumed once and normally leave no trace. When you need to inspect what actually came over the wire — debugging a malformed SSE stream, building replay tooling, capturing a postmortem sample — enable opt-in capture on the response before consuming it:StreamCapturingPolicy::preview(int $maxBytes = 65536)— capture a prefix, enough to see what the stream looked likeStreamCapturingPolicy::chunks(int $maxBytes = 1048576)— retain individual chunks (viacapturedChunks()) up to the byte budgetStreamCapturingPolicy::full(int $maxBytes)— capture everything up to an explicit cap (capturedBody()returns the concatenated content)StreamCapturingPolicy::disabled()— pass-through, zero retention
stream() sees. The truncated flag in stats() tells you when the byte
The default is intentionally disabled because capture adds per-chunk work and
retention to a path designed to stay one-shot. With 50,000–100,000 small chunks,
chunks()/full() can retain 50,000–100,000 PHP string and array entries before
their byte cap is reached; the object overhead can be several times larger than
the payload itself. preview() retains only one bounded prefix, while
disabled() avoids capture storage entirely. Choose a small preview for
diagnostics on long-lived streams and enable full/chunk capture only when the
retained data is explicitly needed.
Considerations
When working with streaming responses, keep these points in mind:- Memory usage. Streaming avoids buffering the entire response, but be careful not to accumulate chunks in a variable unless you actually need the full content.
- Connection stability. Streaming connections stay open longer and are more sensitive to network interruptions. Pair streaming with retry middleware for resilience.
- Timeouts. The
idleTimeoutsetting inHttpClientConfigcontrols how long the client waits between data packets. Set it to-1to disable idle timeouts for long-lived streams. - Body access. Calling
body()on a streamedHttpResponsethrows aLogicException. Always usestream()for streamed responses. - Middleware order. Middleware that decorates the stream (like
EventSourceMiddleware) should be registered before middleware that reads the final content.