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

discord-php/http

Async PHP HTTP client for the Discord REST API. Built for PHP 7.4+ with an event loop and PSR-3 logging. Supports common HTTP verbs, queued requests, JSON-decoded responses, and endpoint constants with parameter binding for correct rate-limit buckets.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel Integration

  1. Install the package in your Laravel project:
    composer require discord-php/http
    
  2. Add a PSR-3 logger (e.g., Monolog):
    composer require monolog/monolog
    
  3. Initialize the HTTP client in a service provider or command:
    use Discord\Http\Http;
    use Discord\Http\Drivers\React;
    use Monolog\Logger;
    use Monolog\Handler\StreamHandler;
    
    $loop = \React\EventLoop\Factory::create();
    $logger = (new Logger('discord_logger'))->pushHandler(new StreamHandler(storage_path('logs/discord.log')));
    $http = new Http(
        config('services.discord.token'), // Your bot token
        $loop,
        $logger
    );
    $http->setDriver(new React($loop));
    
  4. Run the event loop in a Laravel command or Octane worker:
    $loop->run();
    

First Use Case: Fetching Bot Application Info

use Discord\Http\Endpoint;

// Bind endpoint parameters
$endpoint = Endpoint::bind(Endpoint::APPLICATION, config('services.discord.client_id'));

// Make the request
$http->get($endpoint)->done(
    function ($response) {
        // Handle success (e.g., store in cache or log)
        \Log::info('Bot info:', $response);
    },
    function ($error) {
        \Log::error('Failed to fetch bot info:', ['error' => $error->getMessage()]);
    }
);

Implementation Patterns

1. Laravel Command Integration

Wrap the HTTP client in a Laravel command to avoid blocking the CLI process:

use Illuminate\Console\Command;
use React\EventLoop\LoopInterface;

class DiscordSyncCommand extends Command
{
    protected $signature = 'discord:sync';
    protected $description = 'Sync Discord data asynchronously';

    public function handle()
    {
        $loop = \React\EventLoop\Factory::create();
        $http = app(DiscordHttpService::class)->getClient($loop);

        // Queue requests
        $http->get(Endpoint::APPLICATION)->done(
            fn($res) => $this->info('Synced bot info'),
            fn($err) => $this->error($err->getMessage())
        );

        $loop->run();
    }
}

Key: Use artisan discord:sync in a cron job or Laravel scheduler.


2. Rate-Limit-Aware Request Batching

Group requests by rate-limit bucket using Endpoint::bind():

// Batch channel messages (same bucket)
$channelId = '123456789';
$messageIds = ['msg1', 'msg2', 'msg3'];

$requests = array_map(
    fn($id) => $http->get(Endpoint::bind(Endpoint::CHANNEL_MESSAGE, $channelId, $id)),
    $messageIds
);

// Process all in parallel
$promise = \React\Promise\all($requests);
$promise->done(
    fn($responses) => \Log::info('Fetched messages:', $responses),
    fn($err) => \Log::error('Batch failed:', $err)
);

3. Laravel Octane Integration

Deploy the event loop in an Octane worker:

// app/Providers/AppServiceProvider.php
public function boot()
{
    if (config('octane.enabled')) {
        $loop = \React\EventLoop\Factory::create();
        $http = new Http(
            config('services.discord.token'),
            $loop,
            app(\Psr\Log\LoggerInterface::class)
        );
        $http->setDriver(new React($loop));

        // Expose HTTP client to Octane workers
        app()->singleton(DiscordHttpService::class, fn() => new DiscordHttpService($http, $loop));
    }
}

Key: Use app(DiscordHttpService::class) in Octane workers to make requests without blocking HTTP routes.


4. Error Handling and Retries

Implement exponential backoff for retries:

use Discord\Http\Exceptions\RateLimitException;

$http->get(Endpoint::APPLICATION)->otherwise(function ($error) {
    if ($error instanceof RateLimitException) {
        $retryAfter = $error->getRetryAfter();
        $this->info("Rate limited. Retrying in {$retryAfter} seconds...");

        // Schedule retry
        \Bus::dispatch(new RetryDiscordRequest($error->getEndpoint(), $retryAfter));
    }
});

5. Webhook Listeners

Process Discord webhook payloads asynchronously:

// routes/web.php
Route::post('/discord/webhook', function () {
    return response()->json(['status' => 'queued']);
})->middleware('throttle:60,1');

// app/Listeners/DiscordWebhookListener.php
public function handle($payload)
{
    $loop = \React\EventLoop\Factory::create();
    $http = app(DiscordHttpService::class)->getClient($loop);

    // Process payload asynchronously
    $http->post(Endpoint::WEBHOOK_EXECUTE, $payload)->done(
        fn() => \Log::info('Webhook processed'),
        fn($err) => \Log::error('Webhook failed:', $err)
    );

    $loop->run();
}

Gotchas and Tips

1. Event Loop Management

  • Pitfall: Forgetting to run $loop->run() will cause requests to never execute. Fix: Always run the loop in a dedicated process (e.g., Laravel command, Octane worker, or background job).
  • Tip: Use React\Promise\Timer\Timeout to cancel pending requests:
    $promise = $http->get(Endpoint::APPLICATION);
    $promise->otherwise(function ($error) {
        if ($error instanceof \React\Promise\TimeoutException) {
            \Log::warning('Request timed out');
        }
    });
    $promise->otherwise(function () use ($promise) {
        $promise->cancel();
    });
    

2. Rate Limit Buckets

  • Pitfall: Using raw URLs (e.g., /channels/123/messages/456) instead of Endpoint::bind() can cause requests to bypass rate-limit tracking. Fix: Always use Endpoint::bind() for parameterized routes:
    // Correct (rate-limited)
    $endpoint = Endpoint::bind(Endpoint::CHANNEL_MESSAGE, $channelId, $messageId);
    
    // Incorrect (unlimited)
    $endpoint = "channels/{$channelId}/messages/{$messageId}";
    
  • Tip: Monitor rate limits with the X-RateLimit-Reset header:
    $http->get($endpoint)->done(
        function ($response) use ($http) {
            $headers = $http->getLastResponseHeaders();
            $reset = $headers['X-RateLimit-Reset'] ?? null;
            \Log::debug("Rate limit resets at: {$reset}");
        }
    );
    

3. Driver Compatibility

  • Pitfall: The React driver requires ReactPHP (ext-react). If missing, use the Curl driver (synchronous):
    $http->setDriver(new \Discord\Http\Drivers\Curl());
    
  • Tip: For Laravel, prefer the React driver in Octane workers and the Curl driver in HTTP routes:
    $driver = config('app.env') === 'local' ? new React($loop) : new Curl();
    $http->setDriver($driver);
    

4. Logging and Debugging

  • Pitfall: Logs may not appear if the logger isn’t properly configured. Fix: Use Monolog with a file handler:
    $logger = (new Logger('discord'))
        ->pushHandler(new StreamHandler(storage_path('logs/discord.log'), Logger::DEBUG));
    
  • Tip: Enable debug mode for detailed request/response logs:
    $http->setDebug(true); // Logs raw requests/responses
    

5. Laravel Queue Integration

  • Pitfall: Blocking the queue worker with $loop->run(). Fix: Use a separate process or Octane worker for async requests:
    // app/Jobs/ProcessDiscordRequest.php
    public function handle()
    {
        $loop = \React\EventLoop\Factory::create();
        $http = app(DiscordHttpService::class)->getClient($loop);
    
        $http->get(Endpoint::APPLICATION)->done(
            fn() => \Log::info('Job completed'),
            fn($err) => \Log::error('Job failed:', $err)
        );
    
        // Detach the loop from the queue worker
        $loop->run();
    }
    
  • Tip: Use Laravel’s afterCommit hook to ensure database transactions complete before making API calls:
    public function
    
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
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
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