Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Http Client Laravel Package

symfony/http-client

Symfony HttpClient provides a modern API to fetch HTTP resources synchronously or asynchronously. Supports efficient streaming, retries, and multiple transports, making it easy to integrate robust HTTP requests into Symfony or any PHP app.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

Install the package via Composer:

composer require symfony/http-client

Initialize the client in a Laravel service provider or directly in a class:

use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\HttpClient\HttpClient;

public function register()
{
    $this->app->singleton(HttpClientInterface::class, function ($app) {
        return HttpClient::create([
            'timeout' => 30, // seconds
            'base_uri' => 'https://api.example.com/v1/',
            'headers' => [
                'Accept' => 'application/json',
                'Authorization' => 'Bearer ' . $app['auth']->token(),
            ],
        ]);
    });
}

First Use Case: Fetching JSON Data

use Symfony\Contracts\HttpClient\ResponseInterface;

public function fetchData(HttpClientInterface $client)
{
    $response = $client->request('GET', '/users');

    // Get JSON response
    $users = $response->toArray();

    // Or stream the response
    $response->toStreamingIterator(function ($chunk) {
        // Process chunk
    });
}

Key First Steps

  1. Dependency Injection: Use Laravel's service container to manage the client instance.
  2. Configuration: Define base URIs, headers, and timeouts in the client configuration.
  3. Request Methods: Use request(), get(), post(), etc., for different HTTP methods.
  4. Response Handling: Utilize toArray(), toStream(), or getContent() based on needs.

Implementation Patterns

Common Workflows

1. Decorating the Client

Leverage decorators for middleware-like behavior (e.g., logging, caching, retries):

use Symfony\Component\HttpClient\RetryClient;
use Symfony\Component\HttpClient\CachingHttpClient;
use Symfony\Component\HttpClient\Middleware\LoggerMiddleware;

$client = HttpClient::create();
$client = new RetryClient($client, [
    'max_retries' => 3,
    'delay' => 100,
    'max_delay' => 1000,
    'methods' => ['GET', 'POST'],
    'statusCodes' => [503],
]);

$client = new CachingHttpClient($client, new FilesystemCache('/path/to/cache'));
$client = $client->withOptions(['headers' => ['X-Custom-Header' => 'value']]);

2. Handling Async Requests

Use async() for non-blocking requests:

$promise = $client->requestAsync('GET', '/data');
$response = $promise->await(); // Blocking wait
// OR
$promise->then(function (ResponseInterface $response) {
    // Handle response asynchronously
});

3. Streaming Large Responses

Process large responses in chunks:

$response = $client->stream('GET', '/large-file');
$response->toStreamingIterator(function ($chunk) {
    file_put_contents('output.txt', $chunk, FILE_APPEND);
});

4. Retrying Failed Requests

Configure retries for transient failures:

$retryClient = new RetryClient($client, [
    'max_retries' => 3,
    'delay' => 200,
    'methods' => ['GET', 'POST', 'PUT', 'DELETE'],
    'statusCodes' => [429, 500, 502, 503, 504],
]);

5. Scoping Requests

Use ScopingHttpClient for dynamic base URIs:

$scopedClient = new ScopingHttpClient($client, 'https://api.example.com/v2/');
$response = $scopedClient->request('GET', '/users'); // Full URL: https://api.example.com/v2/users

Integration Tips

  • Laravel HTTP Client: Combine with Laravel's Http facade for seamless integration with Laravel's request lifecycle.
  • Middleware: Use Symfony's middleware stack to intercept requests/responses (e.g., for authentication or rate limiting).
  • Testing: Mock HttpClientInterface in tests using Mockery or Laravel's MockHttpClient.

Gotchas and Tips

Pitfalls

  1. Connection Pooling:

    • Issue: Reusing CurlHttpClient instances across requests can lead to connection leaks or timeouts.
    • Fix: Use HttpClient::create() with default settings or configure max_host_connections:
      HttpClient::create(['max_host_connections' => 10]);
      
  2. Streaming Quirks:

    • Issue: Streams may break if the first chunk is delayed (fixed in v8.0.8).
    • Fix: Ensure you’re using the latest version or handle delayed streams gracefully:
      $response = $client->stream('GET', '/stream');
      $response->toStreamingIterator(function ($chunk) {
          if ($chunk === null) {
              // Handle delayed stream
          }
      });
      
  3. Caching Headers:

    • Issue: CachingHttpClient may not respect Cache-Control headers correctly if decorators are misordered.
    • Fix: Place CachingHttpClient after UriTemplate and ScopingHttpClient:
      $client = new CachingHttpClient(
          new ScopingHttpClient(
              new UriTemplateHttpClient($baseClient),
              'https://api.example.com/'
          ),
          $cache
      );
      
  4. Async Response Decoration:

    • Issue: Nested AsyncResponse decorators can cause issues (fixed in v8.0.5).
    • Fix: Avoid deep nesting or update to the latest version.
  5. Timeout Handling:

    • Issue: Destructors may throw exceptions during timeouts (fixed in v8.0.6).
    • Fix: Ensure proper cleanup or use try-catch blocks:
      try {
          $response = $client->request('GET', '/slow-endpoint', ['timeout' => 5]);
      } catch (TransportExceptionInterface $e) {
          // Handle timeout
      }
      
  6. HTTP/3 with Proxies:

    • Issue: HTTP/3 may fail when using proxies (fixed in v8.0.4).
    • Fix: Disable HTTP/3 explicitly if needed:
      HttpClient::create(['options' => ['http_version' => '1.1']]);
      

Debugging Tips

  • Enable Verbose Logging:
    $client = HttpClient::create(['logger' => function ($level, $message, array $context = []) {
        \Log::debug($message, $context);
    }]);
    
  • Inspect Headers/Body:
    $response = $client->request('GET', '/endpoint', [
        'headers' => ['X-Debug' => 'true'],
    ]);
    \Log::debug('Response Headers:', $response->getHeaders());
    \Log::debug('Response Body:', $response->getContent(false));
    
  • Use copyAsCurl() for Debugging:
    $curl = $client->copyAsCurl('GET', '/endpoint');
    \Log::debug('cURL Command:', $curl);
    

Extension Points

  1. Custom Middleware: Create middleware to modify requests/responses:

    use Symfony\Component\HttpClient\Middleware\BaseMiddleware;
    
    class CustomHeaderMiddleware extends BaseMiddleware
    {
        public function __invoke(Request $request, callable $next, callable $first = null)
        {
            $request = $request->withHeader('X-Custom-Header', 'value');
            return $next($request);
        }
    }
    

    Apply it via:

    $client = HttpClient::create(['middlewares' => [new CustomHeaderMiddleware()]]);
    
  2. Event Listeners: Use Symfony’s event system for advanced control:

    $client = HttpClient::create();
    $client->on('request', function (Request $request) {
        \Log::debug('Request:', $request->getUri());
    });
    $client->on('response', function (Response $response) {
        \Log::debug('Status:', $response->getStatusCode());
    });
    
  3. Custom Transport: Implement TransportInterface for specialized needs (e.g., custom proxy logic):

    use Symfony\Component\HttpClient\Transport\TransportInterface;
    
    class CustomTransport implements TransportInterface
    {
        public function sendRequest(Request $request): Response
        {
            // Custom logic
        }
    }
    

    Use it via:

    $client = HttpClient::create(['transport' => new CustomTransport()]);
    

Laravel-Specific Tips

  • Service Provider Binding: Bind the client with environment-based configurations:
    $this->app->singleton(HttpClientInterface::class, function ($app) {
        $config = $app['config']['http_client'];
        return HttpClient::create($config['options'] ?? []);
    });
    
  • **Configuration File
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation
uri-template/tests