HTTP Client Cheat Sheet
Immutability rule:with*() methods return new instances.
Core Entry Points
CanSendHttpRequests
send(HttpRequest $request): PendingHttpResponse
HttpClient
HttpClient::default(): HttpClientHttpClient::using(string $preset, ?string $basePath = null): HttpClientHttpClient::fromConfig(HttpClientConfig $config): HttpClientHttpClient::fromDriver(CanHandleHttpRequest $driver): HttpClient- implements
CanSendHttpRequests send(HttpRequest $request): PendingHttpResponsewithMiddleware(HttpMiddleware $middleware, ?string $name = null): HttpClientwithoutMiddleware(string $name): HttpClientwithMiddlewareStack(MiddlewareStack $stack): HttpClientruntime(): HttpClientRuntimeconfig(): HttpClientConfigwithSSEStream(): HttpClientis deprecated
HttpClientRuntime
HttpClientRuntime::fromConfig(?HttpClientConfig $config, ?CanHandleEvents $events, ?CanHandleHttpRequest $driver, ?CanProvideHttpDrivers $drivers, ?object $clientInstance, ?MiddlewareStack $middlewareStack): HttpClientRuntime(all parameters optional)client(): HttpClientsend(HttpRequest $request): PendingHttpResponsewithMiddleware(HttpMiddleware $middleware, ?string $name = null): selfwithoutMiddleware(string $name): selfwithMiddlewareStack(MiddlewareStack $stack): selfdriver(): CanHandleHttpRequestmiddlewareStack(): MiddlewareStackevents(): CanHandleEventsconfig(): HttpClientConfig
HttpClientBuilder
new HttpClientBuilder(?CanHandleEvents $events = null)withConfig(HttpClientConfig $config): selfwithDsn(string $dsn): selfwithDebugConfig(DebugConfig $debugConfig): selfwithDriver(CanHandleHttpRequest $driver): selfwithDrivers(CanProvideHttpDrivers $drivers): selfwithClientInstance(string $driverName, object $clientInstance): selfwithMiddleware(HttpMiddleware ...$middleware): selfwithRetryPolicy(RetryPolicy $policy): selfwithCircuitBreakerPolicy(CircuitBreakerPolicy $policy, ?CanStoreCircuitBreakerState $stateStore = null): selfwithIdempotencyMiddleware(IdempotencyMiddleware $middleware): selfwithMock(?callable $configure = null): selfwithEventBus(CanHandleEvents $events): selfcreate(): HttpClientcreateRuntime(): HttpClientRuntime
HttpClientConfigFactory
default(): HttpClientConfig
Config
HttpClientConfig
Constructor fields:
driverconnectTimeoutrequestTimeoutidleTimeoutstreamChunkSizestreamHeaderTimeoutfailOnError
HttpClientConfig::group(): stringHttpClientConfig::fromPreset(string $preset, ?string $basePath = null): HttpClientConfigHttpClientConfig::fromDsn(string $dsn): HttpClientConfigHttpClientConfig::fromArray(array $config): HttpClientConfigwithOverrides(array $overrides): selftoArray(): array
curl, guzzle, symfony, http-ollama
DebugConfig
Constructor fields:
httpEnabledhttpTracehttpRequestUrlhttpRequestHeadershttpRequestBodyhttpResponseHeadershttpResponseBodyhttpResponseStreamhttpResponseStreamByLine
DebugConfig::group(): stringDebugConfig::fromPreset(string $preset, ?string $basePath = null): DebugConfigDebugConfig::fromArray(array $config): DebugConfigwithOverrides(array $overrides): selftoArray(): array
Data Types
HttpRequest
Constructor:
new HttpRequest(string $url, string $method, array $headers, string|array $body, array $options, ?string $id = null, ?DateTimeImmutable $createdAt = null, ?DateTimeImmutable $updatedAt = null, ?Metadata $metadata = null)
idcreatedAtupdatedAtmetadata
url(): stringmethod(): stringheaders(?string $key = null): mixedbody(): HttpRequestBodyoptions(): arrayisStreamed(): boolwithHeader(string $key, string $value): selfwithStreaming(bool $streaming): selftoArray(): arrayHttpRequest::fromArray(array $data): HttpRequest
HttpRequestBody
new HttpRequestBody(string|array $body)- arrays are JSON-encoded
- strings are sent verbatim
- JSON encoding failures throw
InvalidArgumentException toString(): stringtoArray(): array
HttpResponse
Factories:
HttpResponse::sync(int $statusCode, array $headers, string $body): HttpResponseHttpResponse::streaming(int $statusCode, array $headers, StreamInterface $stream): HttpResponseHttpResponse::empty(): HttpResponse
statusCode(): intheaders(): arraybody(): stringisStreamed(): boolisStreaming(): boolstream(): GeneratorrawStream(): StreamInterfacewithStream(StreamInterface $stream): HttpResponsetoArray(): arrayHttpResponse::fromArray(array $data): HttpResponse
body()throws for streamed responses
StreamInterface
- extends
IteratorAggregate<int, string> getIterator(): TraversableisCompleted(): bool
PendingHttpResponse
get(): HttpResponsestatusCode(): intheaders(): arraycontent(): stringstream(): Generator
- sync and streamed execution are cached separately
get()follows the request streaming flag
Collections
HttpRequestList
- stores
HttpRequest empty(),of(...),fromArray(...),fromSerializedArray(...)all(),first(),last(),isEmpty(),count(),getIterator()withAppended(),withPrepended(),filter()toArray()
HttpResponseList
- stores
Result<HttpResponse, mixed> empty(),of(...),fromArray(...),fromSerializedArray(...)all(),first(),last(),isEmpty(),count(),getIterator()successful(): list<HttpResponse>failed(): list<mixed>hasFailures(),hasSuccesses()successCount(),failureCount()withAppended(Result $response),filter(),map()toArray()- pooled request results live in
packages/http-pool
Middleware
Contracts and Stack
HttpMiddleware::handle(HttpRequest $request, CanHandleHttpRequest $next): HttpResponseMiddlewareStack:append,appendMany,prepend,prependMany,remove,replace,clear,all,has,get,filter,decorate,toDebugArray
Built-in Middleware
RetryMiddleware(RetryPolicy $policy)CircuitBreakerMiddleware(CircuitBreakerPolicy $policy, ?CanStoreCircuitBreakerState $store)IdempotencyMiddleware(string $headerName, array $methods, ?array $hostAllowList, ?callable $keyProvider)EventSourceMiddleware(bool $enabled)withListeners(CanListenToHttpEvents ...$listeners): selfwithParser(callable $parser): self
RecordReplayMiddleware(string $mode, ?string $storageDir, bool $fallbackToRealRequests, ?EventDispatcherInterface $events)- modes:
MODE_PASS,MODE_RECORD,MODE_REPLAY setMode(string $mode): selfgetMode(): stringsetStorageDir(string $dir): selfsetFallbackToRealRequests(bool $fallback): selfgetRecords(): ?RequestRecords
- modes:
StreamSSEsMiddleware(deprecated, useEventSourceMiddleware::withParser()instead)
- request identity is
method + url + body - headers and request options are not part of record/replay matching
- recording streamed responses buffers the full upstream stream before returning a replayable stream
Drivers
Driver Contract
CanHandleHttpRequest::handle(HttpRequest $request): HttpResponse
Driver Registry
HttpDriverRegistry::make(): HttpDriverRegistryHttpDriverRegistry::fromArray(array $drivers): HttpDriverRegistrywithDriver(string $name, string|callable $driver): selfwithoutDriver(string $name): selfhas(string $name): booldriverNames(): arraymakeDriver(string $name, HttpClientConfig $config, CanHandleEvents $events, ?object $clientInstance = null): CanHandleHttpRequest
Built-in Driver Names
curlguzzlesymfony
Mock Driver
MockHttpDriver
addResponse(HttpResponse|callable $response, string|callable|null $url = null, ?string $method = null, string|callable|null $body = null): selfexpect(): MockExpectationon(): MockExpectationgetReceivedRequests(): arraygetLastRequest(): ?HttpRequestreset(): selfclearResponses(): self
MockExpectation
Matchers:
method(),get(),post(),put(),patch(),delete()url(),urlStartsWith(),urlMatches(),path()header(),headers()withStream()bodyEquals(),bodyContains(),bodyMatchesRegex(),withJsonSubset(),body()times()
reply(HttpResponse|callable $response): MockHttpDriverreplyJson(array|string|\JsonSerializable $data, int $status = 200, array $headers = []): MockHttpDriverreplyText(string $text, int $status = 200, array $headers = []): MockHttpDriverreplyStreamChunks(array $chunks, int $status = 200, array $headers = []): MockHttpDriverreplySSEFromJson(array $payloads, bool $addDone = true, int $status = 200, array $headers = []): MockHttpDriver
MockHttpResponseFactory
success(int $statusCode = 200, array $headers = [], string $body = '', array $chunks = []): HttpResponseerror(int $statusCode = 500, array $headers = [], string $body = '', array $chunks = []): HttpResponsestreaming(int $statusCode = 200, array $headers = [], array $chunks = []): HttpResponsejson(array|string|\JsonSerializable $data, int $statusCode = 200, array $headers = []): HttpResponsesse(array $payloads, bool $addDone = true, int $statusCode = 200, array $headers = []): HttpResponse
- use
withMock(...)for most deterministic client tests - use
MockHttpDriverdirectly when you need request inspection or reusable expectations - use
MockHttpResponseFactoryfor richer JSON, error, streaming, or SSE reply shapes
Exceptions
- Base:
HttpRequestException - Network:
NetworkException,ConnectionException,TimeoutException - HTTP status:
HttpClientErrorException,ServerErrorException - Middleware-related:
CircuitBreakerOpenException - Factory:
HttpExceptionFactory::fromStatusCode(int $statusCode, ?HttpRequest $request, ?HttpResponse $response, ?float $duration, ?Throwable $previous): HttpRequestException
getRequest(): ?HttpRequestgetResponse(): ?HttpResponsegetDuration(): ?floatgetStatusCode(): ?intisRetriable(): bool
Minimal Usage
Basic Request
Streaming Request
Mock Driver
Notes
- pooling lives in
packages/http-pool withDsn()coerces values toHttpClientConfigfield typesEventSourceMiddlewareis the current SSE middleware path