pbweb/buzz-bundle
Symfony bundle integrating the Buzz HTTP client: registers configured client services, adds a web-profiler panel for outgoing requests, and exposes simple YAML configuration for timeouts, headers, and middleware so your app can make outbound HTTP calls cleanly.
composer require pbweb/buzz-bundle. It is a thin Symfony integration around the legacy kriswallsmith/buzz HTTP client, so the transitive dependency is where most of the real API lives.new PBWeb\BuzzBundle\PBWebBuzzBundle() to AppKernel::registerBundles(); on Flex you may still need to enable it manually in config/bundles.php since the bundle predates the recipe system. If nothing appears automatically, this step is the usual culprit.vendor/pbweb/buzz-bundle: DependencyInjection/Configuration.php and Resources/config/services.xml (or .yml). The config tree tells you the exact key names for clients, listeners, timeouts, and proxies; the service definitions tell you the real service IDs and whether they are public/aliased. With a package this small, reading the source is faster than any docs.bin/console debug:container buzz --show-private (or debug:container | grep -i buzz). You are looking for a browser/client service and a listener tag.public function __construct(private \Buzz\Browser $browser) {}
public function __invoke(): void
{
$response = $this->browser->get('https://example.com');
if (!$response->isOk()) {
throw new \RuntimeException('HTTP '.$response->getStatusCode());
}
echo $response->getContent();
}
If autowiring fails (likely, given the bundle's age), wire it explicitly by service id in services.yaml with arguments: ['@buzz.browser'] or whatever debug:container reported.
Treat the bundle as a factory, not a framework. Its job is to build a configured Buzz\Browser (client + listeners) from YAML. Do your request logic in your own service classes and keep the browser as an injected dependency, so you can swap or mock it in tests.
Centralize HTTP calls behind a small client wrapper. Rather than sprinkling $browser->get(...) throughout controllers, create an ApiClient service that owns base URL, auth headers, JSON encoding, and error mapping. This insulates you from Buzz's API being replaced/abandoned later and gives you one place to add retries.
Use listeners for cross-cutting concerns. Buzz's listener/plugin system is the idiomatic extension point, and this bundle typically exposes a way to register them (check Configuration.php for the listener tag or config array). Typical day-to-day uses:
Buzz\Listener\LoggerListener wired to a Monolog channel for request/response logging.Buzz\Listener\BasicAuthListener / OAuth listener for auth headers on every call.Buzz\Listener\CookieListener when talking to a session-based service.class RetryListener implements \Buzz\Listener\ListenerInterface
{
public function preSend(\Buzz\Message\RequestInterface $request): void {}
public function postSend(\Buzz\Message\RequestInterface $request, \Buzz\Message\Response $response): void {}
}
Configure per-environment. Point the bundle's client config at different base URLs / proxies / timeouts for dev vs prod using Symfony parameters and %env()% where supported. If the bundle predates env processors, use parameters.yml overrides instead.
Testing pattern. In functional tests you don't want real sockets. Either replace the browser service with a stub in the test container, or attach a recorder listener and assert against the requests it captured. Because Buzz requests/responses are plain objects (not PSR-7), you can construct Buzz\Message\Request/Response fixtures by hand.
Integration tip: keep the boundary thin. If you already use Symfony's HttpClient, don't mix paradigms per-feature — pick one. A pragmatic approach is to use this bundle only where Buzz's listener chain buys you something (OAuth, cookies, legacy SOAP-ish endpoints) and Symfony HttpClient everywhere else.
kriswallsmith/buzz (Buzz\Browser, Buzz\Message\*) and the modern PSR-18 rewrite (Buzz\Client\*, PSR-7 messages). This bundle targets the legacy one. If Composer resolves a newer Buzz, the classes and API will not match and you'll get Class not found or signature errors. Pin the legacy major in composer.json.services.yml syntax, Request::get() removal). Budget time to patch or fork; treat it as a starting point rather than a maintained dependency.debug:container buzz after install, not before — guessing the id wastes time.getContent(), getStatusCode(), getHeader(), isOk(), isRedirect(). There is no ->getBody()->getContents(). Copy-pasting Symfony HttpClient or Guzzle snippets will fail.Buzz\Exception\ClientException / RequestException; HTTP 4xx/5xx still return a Response. Wrap calls in try/catch and check isOk() separately, or you'll silently treat 500s as success.Client options like timeout, proxy, verify_peer) and the browser config. If a timeout "isn't taking effect," check which layer actually received it with a debug listener that dumps $request->getHeaders().services.yaml is cleaner than forking the bundle.symfony/http-client or Guzzle later is a one-class change.How can I help you explore Laravel packages today?