1

I have this code for creating a Guzzle client with logging:

$loggerMiddleware = new Logger(function ($level, $message, array $context) { ... }

$handler = new CurlMultiHandler();
$stack = HandlerStack::create($handler);
$stack->push($loggerMiddleware);
$client = new Client(['handler' => $stack]);

Now, when I use the other kind of handler, $handler = new CurlHandler();, the Logger function gives me a fully details $context array which has details about the request and repsonse.

The problem is, when I switch to $handler = new CurlMultiHandler();, the $context array no longer has a usable Response, $context['response'] is just meaningless when it's the MultiHandler.

How do I write a logger function where I can get the response back for CurlMultiHandler?

Edit: When I'm in this Logger callback with the useless $context['response'], I notice that I can check $context['reason'] and I see this message:

cURL error 61: Unrecognized content encoding type. libcurl understands deflate, gzip content encodings. (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://courierservices.saasc.uk/api/couriers/v1/Test/create-label

2
  • Is this question related to Laravel or just the Guzzle HTTP client?
    – Eyad Bereh
    Commented Mar 14 at 15:23
  • @EyadBereh i'm try9ing to do it in a laravel project, and if there's a laravel-centric solution I'm interested in it. But maybe it's not so laravel-related.
    – TKoL
    Commented Mar 14 at 15:33

1 Answer 1

0

In Laravel, you can listen to the Illuminate\Http\Client\Events\ResponseReceived event if you're using the built-in Laravel HTTP client (which uses Guzzle's HTTP client under the hood). This event provides two public properties:

  • $request: an instance of Illuminate\Http\Client\Request class, which you can use to further access more details about the outgoing request being done.
  • $response: an instance of Illuminate\Http\Client\Response class, which you can use to further access more details about the incoming response.

You may want to create a listener that listen to this event, for example:

<?php

namespace App\Listeners;

use Illuminate\Http\Client\Events\ResponseReceived;

class LogGuzzleResponse
{
    /**
     * Handle the event.
     */
    public function handle(ResponseReceived $event): void
    {
        info($event->request->headers());
        info($event->request->body());

        info($event->response->headers());
        info($event->response->body());
    }
}

And then you can bind this listener to the event inside the $listen attribute of your App\Providers\EventServiceProvider class as follows:

<?php

namespace App\Providers;

use App\Listeners\LogGuzzleResponse;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Http\Client\Events\ResponseReceived;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event to listener mappings for the application.
     *
     * @var array<class-string, array<int, class-string>>
     */
    protected $listen = [
        ResponseReceived::class => [
            LogGuzzleResponse::class
        ]
    ];
}

As you can see, this approach doesn't require you to use any middleware at all, and it works seamlessly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.