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:
- driver
- connectTimeout
- requestTimeout
- idleTimeout
- streamChunkSize
- streamHeaderTimeout
- failOnError
Methods:
- HttpClientConfig::group(): string
- HttpClientConfig::fromPreset(string $preset, ?string $basePath = null): HttpClientConfig
- HttpClientConfig::fromDsn(string $dsn): HttpClientConfig
- HttpClientConfig::fromArray(array $config): HttpClientConfig
- withOverrides(array $overrides): self
- toArray(): array
Available presets: curl, guzzle, symfony, http-ollama
DebugConfig¶
Constructor fields:
- httpEnabled
- httpTrace
- httpRequestUrl
- httpRequestHeaders
- httpRequestBody
- httpResponseHeaders
- httpResponseBody
- httpResponseStream
- httpResponseStreamByLine
Methods:
- DebugConfig::group(): string
- DebugConfig::fromPreset(string $preset, ?string $basePath = null): DebugConfig
- DebugConfig::fromArray(array $config): DebugConfig
- withOverrides(array $overrides): self
- toArray(): 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)
Readonly lifecycle fields:
- id
- createdAt
- updatedAt
- metadata
Methods:
- url(): string
- method(): string
- headers(?string $key = null): mixed
- body(): HttpRequestBody
- options(): array
- isStreamed(): bool
- withHeader(string $key, string $value): self
- withStreaming(bool $streaming): self
- toArray(): array
- HttpRequest::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): HttpResponse
- HttpResponse::streaming(int $statusCode, array $headers, StreamInterface $stream): HttpResponse
- HttpResponse::empty(): HttpResponse
Methods:
- statusCode(): int
- headers(): array
- body(): string
- isStreamed(): bool
- isStreaming(): bool
- stream(): Generator
- rawStream(): StreamInterface
- withStream(StreamInterface $stream): HttpResponse
- toArray(): array
- HttpResponse::fromArray(array $data): HttpResponse
Note:
- body() throws for streamed responses
StreamInterface¶
- extends
IteratorAggregate<int, string> getIterator(): TraversableisCompleted(): bool
PendingHttpResponse¶
get(): HttpResponsestatusCode(): intheaders(): arraycontent(): stringstream(): Generator
Notes:
- 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): selfRecordReplayMiddleware(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(): ?RequestRecordsStreamSSEsMiddleware(deprecated, useEventSourceMiddleware::withParser()instead)
Record/replay notes:
- 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()
Replies:
- reply(HttpResponse|callable $response): MockHttpDriver
- replyJson(array|string|\JsonSerializable $data, int $status = 200, array $headers = []): MockHttpDriver
- replyText(string $text, int $status = 200, array $headers = []): MockHttpDriver
- replyStreamChunks(array $chunks, int $status = 200, array $headers = []): MockHttpDriver
- replySSEFromJson(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
Testing guidance:
- 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
Useful exception methods:
- getRequest(): ?HttpRequest
- getResponse(): ?HttpResponse
- getDuration(): ?float
- getStatusCode(): ?int
- isRetriable(): bool
Minimal Usage¶
Basic Request¶
use Cognesy\Http\Data\HttpRequest;
use Cognesy\Http\HttpClient;
$client = HttpClient::default();
$response = $client->send(new HttpRequest(
url: 'https://api.example.com/health',
method: 'GET',
headers: ['Accept' => 'application/json'],
body: '',
options: [],
))->get();
echo $response->statusCode();
Streaming Request¶
$request = (new HttpRequest(
url: 'https://api.example.com/stream',
method: 'GET',
headers: ['Accept' => 'text/event-stream'],
body: '',
options: [],
))->withStreaming(true);
foreach ($client->send($request)->stream() as $chunk) {
echo $chunk;
}
Mock Driver¶
use Cognesy\Http\Creation\HttpClientBuilder;
$client = (new HttpClientBuilder())
->withMock(function ($mock) {
$mock->expect()
->get('https://api.example.com/health')
->replyJson(['ok' => true]);
})
->create();
Notes¶
- pooling lives in
packages/http-pool withDsn()coerces values toHttpClientConfigfield typesEventSourceMiddlewareis the current SSE middleware path