Guzzleでリクエスト・レスポンスのログを出す
#php #GuzzleHttp
"guzzlehttp/guzzle": "7.4.5" で確認
https://docs.guzzlephp.org/en/stable/handlers-and-middleware.html
Middleware::log というユーティリティもあるけど、これはrequestとresponseが1行で出る。
以下は2つに分けて出したい場合の例。
code:php
<?php
declare(strict_types=1);
namespace My\App
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
class Client
{
ptivate GuzzleClient $client;
ptivate LoggerInterface $logger;
public function __construct(string $uri, LoggerInterface $logger)
{
if (empty($uri)) {
throw new \RuntimeException('$uri cannot be empty');
}
$this->logger = $logger;
// デバッグ用に通信内容をログに出す
$stack = HandlerStack::create();
$stack->push(Middleware::tap(function(RequestInterface $req) use ($logger) {
$logger->debug(sprintf('--> %s %s %s', $req->getMethod(), $req->getUri(), $req->getBody()->getContents()));
}, function($req, $opt, $res) use ($logger) {
// 第3引数には middleware から $response が渡されるが、実際には Response オブジェクトではなく Promise が来る
// アップデートなどで変わると怖いので防御的に書く
if ($res instanceof PromiseInterface) {
$res = $res->wait();
} elseif (!$res instanceof ResponseInterface) {
return; // 未知のオブジェクトならログに出すのは諦める. そもそもデバッグ用なので
}
$logger->debug(sprintf('<-- %s %s %s', $res->getStatusCode(), $res->getReasonPhrase(), $res->getBody()->getContents()));
}));
$this->client = new GuzzleClient([
'base_uri' => $uri,
'handler' => $stack,
'http_errors' => false, // HTTP 4xx, 5xx を例外にせず自前でハンドリングする場合
]);
}