Weave 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

Curl Bundle Laravel Package

dvelopment/curl-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle to your composer.json:

    composer require dvelopment/curl-bundle
    

    Enable it in config/bundles.php (Symfony):

    return [
        // ...
        Development\CurlBundle\DevelopmentCurlBundle::class => ['all' => true],
    ];
    
  2. Basic Configuration Configure the bundle in config/packages/development_curl.yaml:

    development_curl:
        default_options:
            CURLOPT_TIMEOUT: 30
            CURLOPT_RETURNTRANSFER: true
        clients:
            api:
                base_uri: 'https://api.example.com'
                options:
                    CURLOPT_HTTPHEADER: ['Content-Type: application/json']
    
  3. First Request Inject the CurlClient service and make a request:

    use Development\CurlBundle\Client\CurlClient;
    
    class MyService
    {
        public function __construct(private CurlClient $curl)
        {
        }
    
        public function fetchData()
        {
            $response = $this->curl->request('GET', '/endpoint', [
                'client' => 'api', // Uses configured 'api' client
            ]);
            return json_decode($response, true);
        }
    }
    
  4. Laravel-Specific Setup If using Laravel (not Symfony), manually register the bundle in AppServiceProvider:

    public function register()
    {
        $this->app->register(\Development\CurlBundle\DevelopmentCurlBundle::class);
    }
    

Implementation Patterns

Common Workflows

1. Named Clients for Reusability

Define clients in config for repeated use (e.g., api, payment_gateway):

clients:
    payment_gateway:
        base_uri: 'https://pay.example.com/v1'
        options:
            CURLOPT_HTTPHEADER: ['Authorization: Bearer %token%']

Use placeholders (e.g., %token%) for dynamic values:

$this->curl->request('POST', '/charge', [
    'client' => 'payment_gateway',
    'replace' => ['%token%' => $authToken],
]);

2. Request/Response Handling

  • Streaming Large Responses: Disable CURLOPT_RETURNTRANSFER and stream directly:
    $this->curl->request('GET', '/large-file', [
        'client' => 'default',
        'options' => [CURLOPT_RETURNTRANSFER => false],
    ]);
    
  • Error Handling: Check $response['error'] or use callbacks:
    $response = $this->curl->request('GET', '/data', [
        'on_error' => function ($error) {
            \Log::error('Curl error:', ['error' => $error]);
        },
    ]);
    

3. Authentication

  • Basic Auth:
    clients:
        secure_api:
            options:
                CURLOPT_HTTPAUTH: CURLAUTH_BASIC
                CURLOPT_USERPWD: 'username:password'
    
  • OAuth Tokens: Use replace for dynamic tokens (see above).

4. Retry Logic

Implement retries in a service layer:

public function withRetry($url, $maxRetries = 3)
{
    $retries = 0;
    while ($retries < $maxRetries) {
        try {
            return $this->curl->request('GET', $url);
        } catch (\Exception $e) {
            $retries++;
            if ($retries === $maxRetries) throw $e;
            sleep(2 ** $retries); // Exponential backoff
        }
    }
}

5. Integration with Laravel HTTP Client

Bridge to Laravel’s Http client for consistency:

use Illuminate\Support\Facades\Http;

class CurlBridge
{
    public function __construct(private CurlClient $curl) {}

    public function toLaravelResponse($curlResponse)
    {
        return Http::response(
            $curlResponse['body'],
            $curlResponse['http_code'],
            $curlResponse['headers']
        );
    }
}

Laravel-Specific Patterns

1. Service Container Integration

Bind the CurlClient to Laravel’s container:

$this->app->bind('curl', function ($app) {
    return $app->make('development.curl.client');
});

Then inject via constructor:

public function __construct(private $curl) {}

2. Artisan Commands

Use the bundle in CLI tasks:

use Development\CurlBundle\Client\CurlClient;

class SyncDataCommand extends Command
{
    protected $curl;

    public function __construct(CurlClient $curl)
    {
        parent::__construct();
        $this->curl = $curl;
    }

    public function handle()
    {
        $data = $this->curl->request('GET', '/sync');
        // Process data...
    }
}

3. Queueable Jobs

Offload curl requests to queues:

class ExternalApiJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable;

    public function handle(CurlClient $curl)
    {
        $curl->request('POST', '/process', ['data' => $this->payload]);
    }
}

Gotchas and Tips

Pitfalls

1. Config Overrides

  • Issue: Default options may be silently overridden. Fix: Explicitly merge options:
    $this->curl->request('GET', '/endpoint', [
        'client' => 'api',
        'options' => array_merge(
            $this->container->getParameter('development_curl.clients.api.options'),
            [CURLOPT_TIMEOUT => 60]
        ),
    ]);
    

2. Resource Leaks

  • Issue: Forgetting to close handles (though the bundle likely manages this). Fix: Use try-finally for critical sections:
    $ch = $this->curl->getHandle('GET', '/resource');
    try {
        // Use $ch
    } finally {
        curl_close($ch);
    }
    

3. SSL Certificate Errors

  • Issue: Self-signed certs may fail silently. Fix: Configure in default_options:
    default_options:
        CURLOPT_SSL_VERIFYPEER: false
        CURLOPT_SSL_VERIFYHOST: 0
    
    Warning: Only for testing; use proper certs in production.

4. Placeholders Not Replaced

  • Issue: %token% or other placeholders may not resolve. Fix: Verify replace keys match exactly:
    $this->curl->request('GET', '/data', [
        'client' => 'api',
        'replace' => ['%token%' => $token], // Case-sensitive!
    ]);
    

5. Laravel-Symfony Mismatch

  • Issue: Bundle assumes Symfony’s container. Fix: Manually bind services or extend the bundle:
    $this->app->extend('development.curl.client', function ($app, $client) {
        return new LaravelCurlClient($client); // Custom wrapper
    });
    

Debugging Tips

1. Enable Verbose Output

Add to default_options:

default_options:
    CURLOPT_VERBOSE: true

Log the output:

$this->curl->request('GET', '/debug', [
    'on_info' => function ($info) {
        \Log::debug('Curl info:', ['info' => $info]);
    },
]);

2. Check HTTP Codes

Inspect $response['http_code'] for non-200 responses:

if ($response['http_code'] === 401) {
    throw new \RuntimeException('Unauthorized');
}

3. Validate Headers

Headers may be case-insensitive in some PHP versions:

$headers = $response['headers'];
$contentType = strtolower($headers['Content-Type'] ?? '');

4. Test Locally with curl

Replicate requests using command-line curl to isolate issues:

curl -X GET "https://api.example.com/endpoint" \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json"

Extension Points

1. Custom Response Handlers

Extend the bundle to parse responses:

class JsonResponseHandler
{
    public function handle($response)
    {
        return json_decode($response['body'], true);
    }
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.
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus