Download the PHP package zlodes/http-client without Composer
On this page you can find all versions of the php package zlodes/http-client. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download zlodes/http-client
More information about zlodes/http-client
Files in zlodes/http-client
Package http-client
Short Description Observable, type-safe HTTP client for modern PHP
License proprietary
Informations about the package http-client
zlodes/http-client
Observable, type-safe HTTP client for PHP 8.4+.
Generic Request<TResponse> ensures $client->send(request: $request) returns the correct response type — verified by PHPStan at max level.
Features
- Type-safe — generic
Request<TResponse>toTResponseflow, fully validated by PHPStan - Composable — middleware pipeline for auth, retries, logging, metrics, tracing, and custom concerns
- Framework-agnostic — depends only on PSR interfaces (
psr/http-message,psr/http-client) - Fiber-compatible — synchronous API that transparently supports async via AMP/Revolt fibers
- Flexible hydration — default
ResponseHydratoron the client, per-request override viaHasResponseHydrator - Typed error handling — map
4xx/5xxresponses into typed exceptions with reusable error handlers - Per-request timeouts — set total and connect timeouts globally, per client, or per endpoint
- Default headers — set one header on every request; a caller-supplied value wins
Installation
You'll also need a PSR-7 implementation and any PSR-18 HTTP client, for example:
Optional integrations such as logging and metrics are up to your application and middleware choices.
Quick Start
Define a request
Define a response
Implement a hydrator
Wire it together
Empty Response (Fire-and-Forget Requests)
For requests that don't return a meaningful body (e.g., DELETE, PUT that returns 204), use EmptyResponse to skip hydration entirely:
The client detects EmptyResponse and returns a shared singleton instance — no hydrator is invoked, no deserialization happens.
Collection Responses
For endpoints that return a JSON array of items (e.g. GET /users → [{...}, {...}]), implement CollectionRequest<TItem> to get a typed, iterable response without writing a per-endpoint wrapper.
Branch on CollectionRequest inside your hydrator and use CollectionResponse::fromHydrated() to build a typed response from a denormalizer payload of unknown shape — it validates the array shape and the element types at runtime and gives you back a CollectionResponse<TItem> without manual @var casts:
Per-Request Hydration Override
For APIs that need custom parsing, implement HasResponseHydrator on the request:
The client checks for HasResponseHydrator first, then falls back to the default hydrator.
Error Responses
HttpClient::send() treats 4xx/5xx responses as failures. Register ErrorResponseHandler implementations to turn those responses into typed exceptions.
Register handlers globally on the client, after the middleware array:
Or per request with HasErrorResponseHandlers; request-level handlers are checked before client-level ones.
Timeouts
Timeouts travel with the request as a TransportOptions value. null means "not set here" and never overwrites a value set earlier, so precedence is always the same: request > client > global default.
For a single endpoint, implement HasTransportOptions. Those values win over everything else:
WithTimeout only adds a TimeoutMiddleware to the pipeline, so the same behaviour is available without the factory:
The bundled Psr18Transport ignores them. PSR-18 has no per-request options, so configure timeouts on the wrapped client instead. To honour per-request options, implement your own Transport and read them from the TransportOptions argument. Throw TransportTimeoutException (extends TransportException) on timeout so callers can tell a timeout from a refused connection.
Default headers
Each option sets one header. Stack them for more. If the request already has that header, the caller's value is left as-is. Header names are matched case-insensitively.
WithHeader only adds a HeaderMiddleware to the pipeline, so the same behaviour is available without the factory:
Middleware
Middleware follows an onion model. Each middleware receives a RequestContext and a RequestHandler $next:
Logging example
Metrics example
Wire them in by passing middleware instances to HttpClient:
ClientFactory
For applications with multiple API clients sharing common configuration (transport, logging middleware, hydrator), use ClientFactory with composable options instead of constructing HttpClient directly.
Available options
| Option | Behavior |
|---|---|
WithTransport(Transport) |
Sets the transport (last-writer-wins) |
WithResponseHydrator(ResponseHydrator) |
Sets the hydrator (last-writer-wins) |
WithMiddleware(Middleware ...) |
Appends middlewares (additive) |
WithErrorResponseHandler(ErrorResponseHandler ...) |
Appends error handlers (additive) |
WithBaseUri(UriInterface) |
Sets the base URI (last-writer-wins) |
WithTimeout(?timeout, ?connectTimeout) |
Appends a TimeoutMiddleware (additive) |
WithHeader(name, value) |
Appends a HeaderMiddleware (additive) |
Defaults are applied first, then make() options on top. Last-writer-wins options can be overridden per client; additive options accumulate across defaults and make() calls.
Custom client creator
Pass a custom closure to control how HttpClient is instantiated: