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

Guzzle Laravel Package

guzzlehttp/guzzle

Guzzle is a PHP HTTP client for sending sync or async requests with an easy API. Built on PSR-7 and PSR-18, supports middleware, cookies, streaming uploads/downloads, and JSON. Transport-agnostic for flexible integrations.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require guzzlehttp/guzzle:^7.14

Ensure your composer.json targets Guzzle 7.14.x (latest stable) with PHP 8.1+ for full compatibility. The package now strictly enforces guzzlehttp/psr7:^2.12.5.

  1. First Request (Unchanged):

    use GuzzleHttp\Client;
    
    $client = new Client();
    $response = $client->get('https://api.example.com/data');
    $data = json_decode($response->getBody(), true);
    
  2. Key Entry Points (Updated):

    • Client: Core class with stricter multiplexing/connection validation.
    • Middleware: Enhanced credential redaction and proxy handling.
    • Promises: Fixed race conditions in async completion callbacks.
    • Streaming: Explicit rejection of stream => true on cap-configured handlers.
  3. Where to Look First:


Implementation Patterns

1. Request Construction (Unchanged)

$response = $client->request('GET', '/users', [
    'query' => ['role' => 'admin'],
    'headers' => ['Accept' => 'application/json'],
]);

2. Middleware Workflows (Updated)

  • Credential Redaction:
    $stack->push(Middleware::tap(function ($request) {
        // Credentials in URIs (e.g., `http://user:pass@...`) are now **always redacted** in logs.
        logger()->debug('Request URI:', ['uri' => (string)$request->getUri()]);
    }));
    
  • Proxy Handling:
    $client = new Client([
        'proxy' => 'http://proxy.example.com:8080',
        'proxy_credentials' => 'user:pass', // Now normalized before reuse checks.
    ]);
    

3. Async/Await Patterns (Fixed)

  • Race Condition Fix:
    $promises = [];
    foreach ($urls as $url) {
        $promises[] = $client->getAsync($url);
    }
    // Use `settle()` to avoid double-settling issues:
    $results = \GuzzleHttp\Promise\Utils::settle($promises)->wait();
    

4. Streaming Large Files (Restricted)

  • Cap-Configured Handlers:
    // ❌ Throws `InvalidArgumentException`:
    $client->get('https://example.com/large_file', [
        'stream' => true,
        'handler' => new \GuzzleHttp\Handler\CurlMultiHandler(['capabilities' => ['stream' => true]]),
    ]);
    
  • Workaround: Use StreamHandler without caps or disable streaming:
    $client->get('https://example.com/large_file', ['sink' => 'file.zip']);
    

5. Configuration Management (Stricter)

  • Multiplexing Requirements:
    $client = new Client([
        'curl' => [
            CURLOPT_HTTPAUTH => CURLAUTH_ANY, // ❌ Rejected if NTLM is permitted.
            CURLOPT_PIPELINING => CURLPIPE_MULTIPLEX, // Must be integer.
        ],
        'multiplex' => true,
    ]);
    
  • Proxy Validation:
    // ❌ Throws `InvalidArgumentException`:
    $client = new Client(['proxy' => 'http://user:pass@proxy:8080@invalid']);
    

6. Integration with Laravel (Unchanged)

$app->singleton(GuzzleHttp\Client::class, function ($app) {
    return new Client([
        'base_uri' => config('services.api.base_url'),
        'timeout' => config('services.api.timeout'),
        'proxy' => env('HTTP_PROXY'), // Now normalized.
    ]);
});

Gotchas and Tips

Pitfalls

  1. Proxy Credential Normalization:

    • Issue: Proxy credentials with multiple @ (e.g., user:pass@proxy@domain) now fail closed if unparseable.
    • Fix: Use user:[email protected] format. Validate with:
      if (strpos($proxy, '@@') !== false) {
          throw new \InvalidArgumentException('Invalid proxy credentials');
      }
      
  2. Multiplexing Conflicts:

    • Issue: Combining multiplex => true with:
      • Non-integer CURLMOPT_PIPELINING.
      • CURLOPT_HTTPAUTH allowing NTLM.
      • Cleartext proxies without CURLOPT_PROXYAUTH.
    • Fix: Explicitly configure:
      $client = new Client([
          'multiplex' => true,
          'curl' => [
              CURLOPT_PIPELINING => 1, // Integer required.
              CURLOPT_HTTPAUTH => CURLAUTH_BASIC, // Avoid NTLM.
          ],
      ]);
      
  3. Streaming Restrictions:

    • Issue: stream => true is rejected on handlers with capabilities (e.g., CurlMultiHandler).
    • Fix: Use sink for downloads or disable caps:
      $handler = new \GuzzleHttp\Handler\CurlHandler(); // No caps.
      $client = new Client(['handler' => $handler]);
      
  4. Credential Redaction:

    • Issue: URIs with embedded credentials (e.g., http://user:pass@...) are always redacted in logs/middleware.
    • Fix: Avoid URIs with credentials; use headers:
      $client->get('https://api.example.com', [
          'auth' => ['user', 'pass'], // Preferred over URI credentials.
      ]);
      
  5. Async Promise Race Conditions:

    • Issue: Promises may double-settle if canceled from completion callbacks.
    • Fix: Use settle() or all():
      \GuzzleHttp\Promise\Utils::settle($promises)->wait();
      
  6. Case-Insensitive Matching:

    • Issue: Cookies/proxy schemes/auth types now use ASCII folding (locale-independent).
    • Fix: Ensure headers/auth values are ASCII-compatible:
      $client->request('GET', '/', [
          'headers' => ['Authorization' => 'Bearer ' . $token], // ASCII-safe.
      ]);
      

Debugging Tips

  1. Proxy Validation Errors:

    • Enable debug mode to see rejected proxy values:
      $client = new Client(['debug' => true]);
      // Logs: "Proxy credential 'user:pass@proxy@domain' is invalid."
      
  2. Multiplexing Warnings:

    • Check for conflicts in CURLOPT_* options:
      try {
          $client->request('GET', '/');
      } catch (\InvalidArgumentException $e) {
          echo $e->getMessage(); // "Multiplexing conflict: NTLM auth not allowed."
      }
      
  3. Streaming Handler Errors:

    • Verify on_trailers callbacks are only used with CurlHandler:
      // ❌ Throws on StreamHandler:
      $client->request('GET', '/', [
          'on_trailers' => function ($trailers) { /* ... */ },
      ]);
      
  4. Connection Reuse Signatures:

    • Proxy credentials are now normalized before computing connection signatures. Clear old caches if reuse fails.

Performance Optimization

  1. Multiplexing Safety:

    • Explicitly enable for high-throughput:
      $client = new Client([
          'multiplex' => true,
          'curl' => [CURLOPT_PIPELINING => 1],
      ]);
      
    • Avoid on 32-bit systems (integer overflow risk in delay timing).
  2. Async Event Loop:

    • Use ReactPHP with fixed cURL multi blocking:
      $loop = React\EventLoop\Factory::create();
      $client = new Client([
          'handler' => new \GuzzleHttp\Handler\React\EventLoopHandler($loop),
      ]);
      

Extension Points

  1. Custom Handlers:
    • CurlMultiHandler: Now rejects `stream =>
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.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle