Installation
composer require php-http/httplug-bundle
Register the bundle in config/bundles.php (Symfony Flex handles this automatically).
Basic Configuration
Edit config/packages/httplug.yaml to define your HTTP client stack:
httplug:
clients:
default:
factory: 'http\adapter\guzzle7\client'
plugins:
- 'http\message\serialize\serializer'
- 'http\message\auth\authenticator'
First Use Case Inject the client into a service/controller and make a request:
use Http\Client\Common\Plugin\PluginClient;
use Http\Client\Common\PluginClientFactory;
public function __construct(PluginClient $client) {
$this->client = $client;
}
public function fetchData() {
$response = $this->client->request('GET', 'https://api.example.com/data');
return $response->getBody();
}
config/packages/httplug.yaml (Primary configuration file).Client Configuration
Define clients in httplug.yaml with plugins (e.g., authentication, retries, logging):
httplug:
clients:
api:
factory: 'http\adapter\symfony5\client'
plugins:
- 'http\message\auth\basic_auth'
- 'http\plugin\cache\cache_plugin'
- 'http\plugin\history\history_plugin'
Dependency Injection
Inject PluginClient or ClientInterface into services/controllers:
public function __construct(
private PluginClient $apiClient,
private ClientInterface $defaultClient
) {}
Request Handling Use fluent methods for requests/responses:
$response = $this->apiClient
->request('POST', '/endpoint', [
'json' => ['key' => 'value'],
'headers' => ['Authorization' => 'Bearer token']
]);
$data = json_decode($response->getBody(), true);
Plugin Chaining Reuse plugins across clients or services:
httplug:
plugins:
retry:
class: 'http\plugin\retry\retry_plugin'
config: {max_retries: 3}
clients:
resilient:
factory: 'http\adapter\guzzle7\client'
plugins: ['@retry']
http\adapter\symfony5\client for seamless integration with Symfony’s HttpClient.HttpClient middleware (e.g., Symfony\Contracts\HttpClient\Middleware\RetryMiddleware).ClientInterface in tests:
$this->mockery->mock('overload:Http\Client\Common\ClientInterface');
Plugin Order Matters Plugins execute in the order defined. Authentication should precede serialization:
plugins:
- 'http\message\auth\authenticator' # First
- 'http\message\serialize\serializer' # Second
Factory Class Names
Use fully qualified names (e.g., http\adapter\guzzle7\client, not guzzle7). Check the client list for exact names.
Symfony 6+ Compatibility
For Symfony 6+, use http\adapter\symfony6\client instead of symfony5.
Caching Headers
If using cache_plugin, ensure responses include Cache-Control headers. Otherwise, cached responses may be stale.
Enable Logging Add a logging plugin to debug requests/responses:
plugins:
- 'http\plugin\log\log_plugin'
Configure Monolog to log HTTP traffic.
Validate Responses
Check for Http\Client\Exception or Http\Client\Exception\NetworkException:
try {
$response = $client->request('GET', 'https://invalid.url');
} catch (\Http\Client\Exception\NetworkException $e) {
// Handle network errors
}
Custom Plugins Create reusable plugins (e.g., for API rate limiting):
use Http\Client\Common\Plugin;
use Http\Message\RequestInterface;
class RateLimitPlugin implements Plugin {
public function handleRequest(RequestInterface $request): RequestInterface {
// Add rate-limiting headers
return $request->withHeader('X-RateLimit', '100');
}
}
Register in config/packages/httplug.yaml:
plugins:
rate_limit:
class: 'App\Plugin\RateLimitPlugin'
Dynamic Client Factories Use Symfony’s service container to dynamically configure clients:
httplug.clients.api.factory: '@app.http_client_factory'
// src/Service/HttpClientFactory.php
class HttpClientFactory {
public function __invoke(): ClientInterface {
return new \Http\Adapter\Guzzle7\Client();
}
}
Environment-Specific Config
Override client configurations per environment (e.g., httplug.dev.yaml):
# config/packages/httplug.dev.yaml
httplug:
clients:
default:
factory: 'http\adapter\symfony5\client'
plugins: ['@debug_plugin']
How can I help you explore Laravel packages today?