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 robust API to fetch HTTP resources synchronously or asynchronously. It supports modern features like concurrent requests and streaming, and integrates cleanly with the Symfony ecosystem for building reliable HTTP clients.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup in Laravel
Install the package via Composer:
```bash
composer require symfony/http-client

First Use Case: Fetching a URL

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

// Basic synchronous request
$client = HttpClient::create();
$response = $client->request('GET', 'https://api.example.com/data');
$content = $response->toArray(); // Convert response to array

Laravel Integration (Service Provider)

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

Accessing the Client in Controllers

use Symfony\Contracts\HttpClient\HttpClientInterface;

public function __construct(private HttpClientInterface $httpClient) {}

public function fetchData()
{
    $response = $this->httpClient->request('GET', '/endpoint');
    return response()->json($response->toArray());
}

Implementation Patterns

1. Request Customization

Query Parameters & Headers

$response = $client->request('GET', '/search', [
    'query' => [
        'q' => 'laravel',
        'page' => 1,
    ],
    'headers' => [
        'X-Custom-Header' => 'value',
    ],
]);

Authentication

// Basic Auth
$client->authenticate('username', 'password', 'basic');

// Bearer Token
$client->setDefaultOption('auth_bearer', 'your-token-here');

2. Asynchronous Requests

use Symfony\Contracts\HttpClient\ResponseStream;

// Fire-and-forget
$client->request('GET', '/async-endpoint');

// Stream responses
$responseStream = $client->stream('GET', '/large-file');
foreach ($responseStream as $chunk => $chunkResponse) {
    file_put_contents('file.part', $chunkResponse->getContent());
}

3. Decorators for Advanced Use Cases

Caching Responses

use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Component\HttpClient\CachingHttpClient;

$cache = $this->app->make(CacheInterface::class);
$cachedClient = new CachingHttpClient(
    $client,
    $cache,
    'http_cache_key_%s',
    3600 // TTL in seconds
);

Retry Mechanism

use Symfony\Component\HttpClient\RetryHttpClient;

$retryClient = new RetryHttpClient(
    $client,
    [
        'max_retries' => 3,
        'delay' => 100, // ms
        'max_delay' => 1000, // ms
        'statuses' => [500, 502, 503, 504],
    ]
);

4. Streaming Uploads

$response = $client->request('POST', '/upload', [
    'body' => fopen('large-file.zip', 'r'),
    'headers' => [
        'Content-Type' => 'application/zip',
    ],
]);

5. Middleware for Request/Response Processing

use Symfony\Component\HttpClient\Middleware\MiddlewareInterface;

class LoggingMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, callable $next, callable $first = null)
    {
        \Log::info('Request:', [
            'method' => $request->getMethod(),
            'uri' => (string) $request->getUri(),
        ]);

        $response = $next($request);

        \Log::info('Response:', [
            'status' => $response->getStatusCode(),
            'headers' => $response->getHeaders(),
        ]);

        return $response;
    }
}

// Apply middleware
$client = HttpClient::create(['middleware' => [new LoggingMiddleware()]]);

6. Handling Redirects

// Follow redirects (default: 5)
$client->request('GET', '/redirect-me', [
    'max_redirections' => 10,
]);

// Disable redirects
$client->request('GET', '/no-redirects', [
    'follow_redirects' => false,
]);

7. Proxy Configuration

$client = HttpClient::create([
    'proxy' => [
        'http' => 'tcp://proxy.example.com:8080',
        'https' => 'tcp://proxy.example.com:8080',
    ],
]);

Gotchas and Tips

Common Pitfalls

  1. Resource Leaks with Streams

    • Always ensure streams are properly closed or use finally blocks.
    • Fix: Use finally or try-catch-finally to close streams:
      $response = $client->request('GET', '/stream-endpoint');
      $stream = $response->getContent(false); // Get stream without consuming it
      try {
          // Process stream
      } finally {
          $stream->close();
      }
      
  2. Timeout Handling

    • Default timeout is null (infinite). Set explicit timeouts to avoid hanging requests.
    • Example:
      $client->request('GET', '/slow-endpoint', [
          'timeout' => 10, // 10 seconds
      ]);
      
  3. Connection Pooling Issues

    • Reusing the same client instance for high-concurrency scenarios may lead to connection exhaustion.
    • Solution: Use max_host_connections to limit connections per host:
      $client = HttpClient::create([
          'max_host_connections' => 10,
      ]);
      
  4. Caching Headers Conflicts

    • CachingHttpClient may not work as expected if responses lack proper Cache-Control or ETag headers.
    • Tip: Ensure your API supports caching headers or disable caching for dynamic endpoints.
  5. Async Response Handling

    • Async responses must be awaited or processed in a loop to avoid memory leaks.
    • Example:
      $promise = $client->request('GET', '/async-endpoint');
      $response = $promise->wait(); // Blocking wait
      // OR
      $promise->then(function (ResponseInterface $response) {
          // Handle response
      });
      
  6. SSL/TLS Issues

    • Self-signed certificates or custom CA bundles require explicit configuration.
    • Example:
      $client = HttpClient::create([
          'verify_peer' => true,
          'verify_host' => true,
          'cafile' => __DIR__.'/custom-ca-bundle.crt',
      ]);
      
  7. Decorators Order Matters

    • The order of decorators (e.g., CachingHttpClient, RetryHttpClient) affects behavior.
    • Rule of Thumb: Apply decorators from outermost to innermost (e.g., caching → retries → base client).

Debugging Tips

  1. Enable Verbose Logging

    $client = HttpClient::create([
        'debug' => true,
    ]);
    
    • Logs will include request/response details in the Symfony profiler or Monolog.
  2. Inspect Raw Responses

    $response = $client->request('GET', '/endpoint');
    $content = $response->getContent(); // Raw body
    $headers = $response->getHeaders(); // All headers
    $status = $response->getStatusCode(); // HTTP status
    
  3. Use copyAsCurl() for cURL Debugging

    $request = $client->createRequest('GET', '/endpoint');
    $curlCommand = $request->copyAsCurl();
    \Log::info('cURL command:', [$curlCommand]);
    
    • Copy-paste the generated cURL command into a terminal for manual testing.
  4. Handle Exceptions Gracefully

    try {
        $response = $client->request('GET', '/endpoint');
    } catch (TransportExceptionInterface $e) {
        \Log::error('HTTP transport error:', ['exception' => $e]);
        throw new \RuntimeException('Failed to fetch data', 0, $e);
    } catch (ClientExceptionInterface $e) {
        \Log::error('HTTP client error:', ['status' => $e->getStatusCode()]);
    }
    

Extension Points

  1. Custom HTTP Client
    • Implement HttpClientInterface for protocol-specific clients (e.g., Guzzle, Buzzle).
    • Example:
      use Symfony\Contracts\HttpClient\HttpClientInterface;
      use Symfony\Contracts\HttpClient\RequestInterface;
      use Symfony\Contracts\HttpClient\ResponseInterface;
      
      class CustomHttpClient implements HttpClientInterface
      {
          public function request
      
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope