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 Laravel Package

pdeans/http

Lightweight PSR-7 cURL HTTP client with PSR-17 factory support, built on Laminas Diactoros. Configure via curl options and use helper methods for GET/POST/PUT/PATCH/DELETE/HEAD/TRACE with headers and optional body streams/resources.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require pdeans/http
    

    Add to composer.json under require or require-dev depending on use case.

  2. Basic Usage:

    use pdeans\Http\Client;
    
    $client = new Client();
    $response = $client->get('https://api.example.com/data');
    $data = json_decode((string) $response->getBody(), true);
    
  3. First Use Case: Replace a direct curl_exec() call in a Laravel service with this client. For example:

    // Before (ad-hoc cURL)
    $ch = curl_init('https://api.example.com/data');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    curl_close($ch);
    
    // After (using pdeans/http)
    $client = new Client();
    $response = $client->get('https://api.example.com/data');
    

Where to Look First

  • Client Class: pdeans\Http\Client for HTTP requests.
  • Factories: pdeans\Http\Factories\* for PSR-17-compliant message creation.
  • Response Handling: pdeans\Http\Response for parsing responses.
  • README.md: Focus on the "Usage" section for quick examples.

Implementation Patterns

Usage Patterns

  1. Service Layer Integration: Inject the client into Laravel services for API calls:

    use Illuminate\Support\Facades\Http;
    use pdeans\Http\Client;
    
    class ApiService {
        protected Client $client;
    
        public function __construct(Client $client) {
            $this->client = $client;
        }
    
        public function fetchData() {
            $response = $this->client->get('https://api.example.com/data');
            return json_decode($response->getBody(), true);
        }
    }
    

    Register the client in AppServiceProvider:

    $this->app->bind(Client::class, function ($app) {
        return new Client([
            CURLOPT_TIMEOUT => 10,
            CURLOPT_SSL_VERIFYPEER => true,
        ]);
    });
    
  2. PSR-17 Factories for Dynamic Requests: Use factories to create requests dynamically (e.g., in middleware or tests):

    use pdeans\Http\Factories\RequestFactory;
    
    $requestFactory = new RequestFactory();
    $request = $requestFactory->createRequest('POST', 'https://api.example.com/data');
    $request = $request->withHeader('Content-Type', 'application/json')
                       ->withBody($client->getStream(json_encode(['key' => 'value'])));
    
    $response = $client->sendRequest($request);
    
  3. Error Handling: Wrap client calls in try-catch blocks to handle exceptions (e.g., network errors):

    try {
        $response = $client->get('https://api.example.com/data');
        if ($response->getStatusCode() !== 200) {
            throw new \RuntimeException('API request failed');
        }
    } catch (\Exception $e) {
        Log::error('API call failed: ' . $e->getMessage());
        throw $e;
    }
    
  4. Configuration Management: Centralize cURL options in a config file (e.g., config/http.php):

    return [
        'default_options' => [
            CURLOPT_TIMEOUT => 10,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
        ],
    ];
    

    Load options dynamically:

    $client = new Client(config('http.default_options'));
    

Workflows

  1. API Consumer Workflow:

    • Use helper methods (get, post, etc.) for common HTTP verbs.
    • Parse responses with PSR-7 methods (getBody(), getStatusCode()).
    • Example:
      $response = $client->post('https://api.example.com/data', [
          'Content-Type' => 'application/json',
      ], json_encode(['data' => 'value']));
      
      if ($response->getStatusCode() === 201) {
          return json_decode($response->getBody(), true);
      }
      
  2. Webhook Handling: Use ServerRequestFactory to parse incoming webhook requests:

    use pdeans\Http\Factories\ServerRequestFactory;
    
    $serverRequestFactory = new ServerRequestFactory();
    $serverRequest = $serverRequestFactory->createServerRequest(
        'POST',
        'https://example.com/webhook',
        [],
        [],
        [],
        ['CONTENT_TYPE' => 'application/json']
    );
    
    $body = json_decode($serverRequest->getBody(), true);
    
  3. Testing: Mock the client in unit tests using PSR-7 interfaces:

    $this->mock(Client::class)
         ->shouldReceive('get')
         ->once()
         ->andReturn($this->createMock(ResponseInterface::class));
    

Integration Tips

  1. Laravel HTTP Client Bridge: If using Laravel’s Http facade, consider wrapping this client for consistency:

    Http::macro('pdeans', function ($uri, $config = []) {
        $client = new Client($config);
        return $client->get($uri);
    });
    
  2. Middleware Integration: Use PSR-17 factories to build middleware-compatible requests:

    $request = (new RequestFactory())->createRequest('GET', 'https://api.example.com/data');
    $request = $request->withHeader('X-API-KEY', config('api.key'));
    $response = $client->sendRequest($request);
    
  3. Stream Handling: For large payloads, use streams to avoid memory issues:

    $stream = $client->getStream(fopen('large_file.json', 'r'));
    $response = $client->post('https://api.example.com/upload', [], $stream);
    

Gotchas and Tips

Pitfalls

  1. cURL Option Restrictions:

    • Options like CURLOPT_URL, CURLOPT_POSTFIELDS, or CURLOPT_HTTPHEADER cannot be set via the client constructor. Use the request-specific methods (get, post, etc.) or sendRequest with a custom Request object.
    • Workaround: Use RequestFactory to build requests with custom headers/body.
  2. Resource Leaks:

    • The client does not automatically close cURL handles. Call $client->release() after sending requests if managing resources manually.
    • Tip: Use Laravel’s service container to manage the client’s lifecycle (automatic cleanup).
  3. PSR-7/PSR-17 Learning Curve:

    • Developers unfamiliar with PSR-7 interfaces (e.g., StreamInterface, UriInterface) may struggle with advanced use cases.
    • Tip: Start with helper methods (get, post) and gradually adopt factories for complex scenarios.
  4. No Built-in Retries:

    • Unlike Guzzle, this client lacks retry logic. Implement manually or use a wrapper:
      function withRetry(Client $client, $uri, $maxRetries = 3) {
          $attempts = 0;
          while ($attempts < $maxRetries) {
              try {
                  return $client->get($uri);
              } catch (\Exception $e) {
                  $attempts++;
                  if ($attempts >= $maxRetries) throw $e;
                  sleep(1);
              }
          }
      }
      
  5. SSL Verification:

    • Disabling SSL verification (CURLOPT_SSL_VERIFYPEER => false) is not recommended for production. Use proper certificates or a trusted CA bundle.
    • Tip: Configure SSL options in the client constructor:
      $client = new Client([
          CURLOPT_SSL_VERIFYPEER => true,
          CURLOPT_CAINFO => storage_path('certs/ca-bundle.crt'),
      ]);
      

Debugging

  1. cURL Errors:

    • Check the response status code and body for errors. Enable verbose cURL output for debugging:
      $client = new Client([
          CURLOPT_VERBOSE => true,
      ]);
      
    • Tip: Use CURLOPT_STDERR to log cURL errors to a file:
      $client = new Client([
          CURLOPT_STDERR => fopen(storage_path('logs/curl_errors.log'), 'a'),
      ]);
      
  2. Stream Issues:

    • If streams fail to read/write, ensure the resource is valid and not closed. Use StreamFactory to create streams safely:
      $streamFactory = new StreamFactory();
      $stream = $streamFactory->createStreamFromFile('file.json');
      
  3. Header Conflicts:

    • Headers like Host or User-Agent may be overridden by the client. Use sendRequest with a custom Request object to enforce headers:
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.
cadot.eu/make
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky