2 votes

Laravel - Enregistrer les requêtes Guzzle dans un fichier

En travaillant sur un projet, j'ai constaté que les API tierces fonctionnaient avec Postman, mais pas avec Guzzle Client.

Le débogage d'une requête Guzzle peut s'avérer difficile. Existe-t-il un moyen d'enregistrer toutes les requêtes effectuées par le client Guzzle ?

4voto

TechnoKnol Points 790

TLDR ;

Il existe un moyen simple d'enregistrer toutes les requêtes de Guzzle en passant un second paramètre au Client, qui enregistrera alors toutes les requêtes. Mais c'est une méthode peu pratique si vous avez de nombreuses méthodes utilisant le client Guzzle pour envoyer des requêtes à un serveur tiers. Je l'ai fait en utilisant le conteneur de service de Laravel.

La voie longue via le conteneur de services de Laravel

Lorsque j'ai utilisé le client Guzzle dans mon projet et que j'ai utilisé un handler pour enregistrer toutes les requêtes, tout se passe bien. Mais plus tard, il y avait de nombreuses méthodes dans de nombreuses classes différentes, de sorte que je devais écrire la logique du logger partout. C'est alors que je me suis dit pourquoi ne pas tirer parti de la fonction de logger de Laravel Conteneur de services et lier un objet une fois pour l'utiliser partout.

Voici comment j'ai procédé. Dans votre AppServiceContainer.php nous ajouterons tout notre code. Ensuite, dans les contrôleurs, nous utiliserons notre objet Client.

Ajoutez cette déclaration d'utilisation en plus de la déclaration d'utilisation AppServiceContainer.php archivo.

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\MessageFormatter;
use GuzzleHttp\Middleware;
use Illuminate\Support\ServiceProvider;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger;

Ajoutez le code suivant à votre AppServiceContainer.php boot méthode

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
    {
        $this->app->bind('GuzzleClient', function () {

            $messageFormats = [
                'REQUEST: {method} - {uri} - HTTP/{version} - {req_headers} - {req_body}',
                'RESPONSE: {code} - {res_body}',
            ];

            $stack = HandlerStack::create();

            collect($messageFormats)->each(function ($messageFormat) use ($stack) {
                // We'll use unshift instead of push, to add the middleware to the bottom of the stack, not the top
                $stack->unshift(
                    Middleware::log(
                        with(new Logger('guzzle-log'))->pushHandler(
                            new RotatingFileHandler(storage_path('logs/guzzle-log.log'))
                        ),
                        new MessageFormatter($messageFormat)
                    )
                );
            });

            return function ($config) use ($stack){
                return new Client(array_merge($config, ['handler' => $stack]));
            };
        });
    }

Explication

Si vous avez remarqué le code ci-dessus, dans la première ligne de la méthode boot, nous indiquons à Laravel que nous voulons enregistrer ce code en tant que GuzzleClient dans votre Service Container.

Dans la dernière instruction return, nous renvoyons une fonction qui acceptera un seul argument $config . Nous avons utilisé cette fonction comme un proxy afin de pouvoir lui passer un argument qui pourra être utilisé dans l'objet client.

return function ($config) use ($stack){
      return new Client(array_merge($config, ['handler' => $stack]));
};

Le reste du code construit l'objet Handler de Guzzle pour enregistrer toutes les demandes dans un fichier appelé guzzle-log.log en utilisant l'objet Logger de la bibliothèque Monolog. Si les journaux quotidiens sont activés, une date sera ajoutée au nom du fichier comme suit guzzle-log-2019-08-11.log . Utilisation

Nous avons lié notre objet au conteneur de service, il est maintenant temps d'utiliser ce conteneur partout dans notre code, et de lui donner une apparence propre.

À des fins de démonstration, je l'ai utilisé directement dans routes/web.php fichier. Vous pouvez l'utiliser partout.

 Route::get('/', function () {

    $client = app('GuzzleClient')(['base_uri' => 'http://httpbin.org/']);

    $request = $client->get('get',[
        'query' => ['foo'=>'bar', 'baz' => 'baz2'] ,
        'headers' => [ 'accept' =>  'application/json']
    ]);
    $response = json_decode((string) $request->getBody());
    return response()->json($response);
});

Comme vous pouvez le voir, je crée un objet $client en utilisant app() aide. Vous pouvez également passer un tableau d'arguments valide que le client Guzzle prend en charge en tant que second paramètre. Ici, j'ai passé base_uri .

Log file entry

Source : http://shyammakwana.me/laravel/laravel-log-guzzle-requests-to-file-using-service-container.html

0voto

Osama Sayed Points 1078

La réponse acceptée fonctionne bien en utilisant Prestataires de services . Une autre option consisterait à joindre GuzzleHttp\Middleware 's log à l'endroit où vous utilisez Illuminate\Support\Facades\Http . Un exemple qui enregistre la demande, la réponse et les erreurs éventuelles serait le suivant Middleware::log :

<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger;
use GuzzleHttp\MessageFormatter;
use GuzzleHttp\Middleware;

/**
 * Class TestService
 * @package App
 */
class TestService
{
    private function getAccessToken()
    {
        try {
            $response = Http::asForm()->withMiddleware(Middleware::log(with(new Logger('guzzle-log'))->pushHandler(
                new RotatingFileHandler(storage_path('logs/guzzle-log.log'))
            ), new MessageFormatter(MessageFormatter::DEBUG)))->post("https://test.com/oauth/v2/token", [
                'grant_type' => 'client_credentials',
            ]);
            $response->throw();
        } catch (\Throwable $th) {
            $accessToken = false;
        }
        return $accessToken;
    }
}

Cette opération permet d'écrire les enregistrements dans le fichier logs/guzzle-log-{currentDate}.log fichier. Le format de l'enregistrement que j'ai utilisé dans cet exemple est le suivant MessageFormatter::DEBUG qui est ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}" qui contient la demande, la réponse et les éventuelles erreurs. Un exemple de fichier journal serait le suivant

[2020-08-07T07:13:23.712124+00:00] guzzle-log.INFO: >>>>>>>> POST /oauth/v2/token HTTP/1.1 Content-Length: 29 User-Agent: GuzzleHttp/7 Host: xxxx:4000 Content-Type: application/x-www-form-urlencoded  grant_type=client_credentials <<<<<<<< HTTP/1.1 200 OK X-DNS-Prefetch-Control: off X-Frame-Options: SAMEORIGIN Strict-Transport-Security: max-age=15552000; includeSubDomains X-Download-Options: noopen X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Access-Control-Allow-Origin: * Content-Type: application/json; charset=utf-8 Content-Length: 113 ETag: W/"71-DyA+KEnetTKfUlb0lznokGTt0qk" Date: Fri, 07 Aug 2020 07:13:23 GMT Connection: keep-alive  {"data":{"token_type":"Bearer","access_token":"XYZ","expires_in":"7776000"}} -------- NULL [] []

Note : L'inconvénient de cette option est que vous devrez attacher des withMiddleware(Middleware::log(...)) à n'importe quel endroit où vous utilisez Illuminate\Support\Facades\Http .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X