symfony/http-client-contracts
Symfony HttpClient Contracts provides stable interfaces for HTTP clients and responses, extracted from Symfony. Build libraries against these battle-tested abstractions and swap implementations easily while staying compatible with Symfony’s HttpClient ecosystem.
Architecture fit:
Http facade via adapters (e.g., php-http/guzzle7-adapter or symfony/psr-http-message-bridge). Reduces custom interface code.Http facade (which uses Guzzle under the hood), but can coexist via service binding. Requires explicit refactoring of facade-dependent code to use HttpClientInterface.ResponseInterface::until()), but async requires additional setup (e.g., symfony/http-client’s AsyncHttpClient).Integration feasibility:
symfony/http-client-contracts + a concrete client (e.g., symfony/http-client or guzzlehttp/guzzle).HttpClientInterface to the concrete client in Laravel’s service container.Http::get()/Http::post() directly will need:
HttpClientInterface into services.Http::adapter() or custom wrappers).MockHttpClient or TestHttpClient, but requires updating test doubles to match the interface.Technical risk:
Http facade is tightly coupled to Guzzle. Replacing it with HttpClientInterface may expose edge cases (e.g., middleware, events, or Guzzle-specific features like onStats).symfony/http-client (which supports HTTP/2 and connection pooling).symfony/psr-http-message-bridge).symfony/http-client) will cause runtime errors.Key questions:
Http facade entirely, or introduce HttpClientInterface as a parallel abstraction for new services?symfony/http-client for async/HTTP2 features?Http::fake() or Guzzle mocks?Http::macro()) that would require custom adapters?Stack fit:
HttpClient (for async/HTTP2).guzzlehttp/psr7 or php-http/guzzle7-adapter).Http facade (via adapter layer).symfony/psr-http-message-bridge to unify PSR-7/Symfony message types, but adds complexity.Migration path:
HttpClientInterface in new services/modules.symfony/http-client or Guzzle in config/app.php:
'HttpClientInterface' => fn() => new \Symfony\Component\HttpClient\HttpClient(),
php-http/discovery for auto-discovery of installed clients.Http::get() calls with HttpClientInterface in critical paths (e.g., API clients).Http facade:
class LaravelHttpClient implements HttpClientInterface {
public function request(string $method, string $url, array $options = []): ResponseInterface {
return new LaravelResponse(Http::{$method}($url, $options));
}
}
Http facade in favor of HttpClientInterface.Compatibility:
TrustProxies) won’t work directly. Use Symfony’s HttpClient middleware or custom decorators.Http::on() events require adapter translation to HttpClientInterface.Http::macro() is facade-specific; replace with service providers or decorators.ClientInterface) and PSR-7 (MessageInterface), enabling interoperability with other libraries (e.g., php-http/client).Sequencing:
MockHttpClient or TestHttpClient before migrating production code.HttpClientInterface, deprecate Http:: in favor of the new contract.Maintenance:
HttpClientException for non-2xx statuses), reducing ad-hoc error handling code.Support:
HttpClient provides detailed debug output (enable via HttpClient::create(['debug' => true])). Laravel’s Http facade lacks comparable tooling.symfony/profiler) and community support for HTTP client issues.Http::retry()) may require custom adapters or community packages.Scaling:
symfony/http-client supports connection pooling and HTTP/2, improving performance under load. Guzzle requires manual tuning for similar benefits.AsyncHttpClient or PSR-18 async clients.Failure Modes:
HttpClientInterface to a concrete implementation (e.g., symfony/http-client) causes ClassNotFoundException.ResponseInterface::toArray() throws on empty bodies or non-2xx statuses. Mitigate with:
$response = $client->request('GET', $url, ['throw' => false]);
if ($response->getStatusCode() !== 200) { /* handle error */ }
ResponseInterface::until() or cancel() can hang requests. Use timeouts and cancellation tokens.Ramp-up:
Http facade will need training on:
Http::get() calls).getStatusCode() before toArray()).Http facade).How can I help you explore Laravel packages today?