有时候难免要对 Http 的请求和响应包体进行记录以方便查找问题或做什么。
Laravel 的 Http 客户端是基于 Guzzle 进行封装的,在上层进行了简化,并没有直接给我们留相关的日志配置,想要对请求的 http 进行详细的记录,则需要借助于 Guzzle 的 Handler/中间件,和 withOptions 方法。
首先们要使用 composer 安装一个第三方的 Guzzle 日志中间件。
composer require rtheunissen/guzzle-log-middleware
该中间件比较简单,仅是在请求发生时将请求和响应对象传递给我们指定的闭包,然后我们在闭包中直接调用 Log 的方法进行记录即可。
简单的演示如下:
$stack = new HandlerStack(); $stack->setHandler(new CurlHandler()); //使用 HandlerStack 后必须指定一个 Handler //日志中间件 $logger = new Logger(function ($level, $message, array $context) { Log::log($level, $message); }); $stack->push($logger); $res = Http::withOptions([ 'handler' => $stack ])->post($url, $data);
此时请求发生时我们就会在日志里看到一条这样的简单日志:
[2021-04-28 17:00:30] local.INFO: homestead GuzzleHttp/7 - [28/Apr/2021:17:00:30 +0800] "POST /your/request/url HTTP/1.1" 200 136
不过显示这个日志太简单了,我们需要更详细的信息,比如请求和响应的头信息及主体内容,通过该中间件的主页得知可使用一个闭包来进行 message 的格式化。
于是我们对 Logger 进行一番修改,从 Request 和 Response 中取出相应的信息,并且拼装成 Http 的包体结构,结果如下:
$logger = new Logger(function ($level, $message, array $context) { Log::log($level, $message); }, function ($request, $response, $reason) { /** * @var Request $request * @var Response $response */ $requestBody = $request->getBody(); $requestBody->rewind(); //请求头 $requestHeaders = []; foreach ($request->getHeaders() as $k => $vs) { foreach ($vs as $v) { $requestHeaders[] = "$k: $v"; } } //响应头 $responseHeaders = []; foreach ($response->getHeaders() as $k => $vs) { foreach ($vs as $v) { $responseHeaders[] = "$k: $v"; } } $uri = $request->getUri(); $path = $uri->getPath(); if ($query = $uri->getQuery()) { $path .= '?'.$query; } return sprintf( "Request %s\n%s %s HTTP/%s\r\n%s\r\n\r\n%s\r\n--------------------\r\nHTTP/%s %s %s\r\n%s\r\n\r\n%s", $uri, $request->getMethod(), $path, $request->getProtocolVersion(), join("\r\n", $requestHeaders), $requestBody->getContents(), $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase(), join("\r\n", $responseHeaders), $response->getBody()->getContents() ); });
发送请求后,日志内容如下:
[2021-04-28 17:06:11] local.NOTICE: Request https://www.baidu.com/ POST / HTTP/1.1 User-Agent: GuzzleHttp/7 Content-Type: application/json Host: www.baidu.com {"hello":"I am a fake POST."} -------------------- HTTP/1.1 302 Found Bdpagetype: 3 Connection: keep-alive Content-Length: 154 Content-Type: text/html Date: Wed, 28 Apr 2021 09:06:11 GMT Location: https://www.baidu.com/search/error.html Server: BWS/1.1 Set-Cookie: BDSVRTM=0; path=/ Traceid: 161960077103724047468432068516915727024 X-Ua-Compatible: IE=Edge,chrome=1 <html> <head><title>302 Found</title></head> <body bgcolor="white"> <center><h1>302 Found</h1></center> <hr><center>nginx</center> </body> </html>
怎么样,详细否?