garbetjie / http-request-logger
一个可以记录所有传入和传出请求及响应的请求记录器。
Requires
- php: ^7.3 || ^7.4 || ^8.0
- endyjasmi/cuid: ^2.1
- psr/http-message: ^1.0
- psr/http-server-middleware: ^1.0
- psr/log: ^1.1
Requires (Dev)
- guzzlehttp/guzzle: *
- laravel/framework: ^6.18.35 || ^7.30.4 || ^8.40.0
- orchestra/testbench: ^4.0 || ^5.0 || ^6.0
- phpunit/phpunit: ^8.0 || ^9.0
Suggests
- ext-simplexml: Required for logging SOAP requests.
- ext-soap: Required for logging SOAP requests.
This package is auto-updated.
Last update: 2024-09-19 01:56:02 UTC
README
一个HTTP请求记录库,可轻松实现记录所有HTTP请求和响应。
支持 Laravel、Guzzle 和 PHP 的 SoapServer
和 SoapClient
类。
目录
简介
能够查看应用程序生成的所有请求和响应通常非常有用,尤其是在开发期间。此库使得使用 Monolog 记录所有传入和传出请求和响应变得非常简单。
默认情况下,所有请求和响应都记录在 debug
日志级别。使用合理的默认日志上下文,并且可能包含敏感值的头(如 Cookie
、Set-Cookie
和 Authorization
)的值被混淆。每个请求和相应的响应通过一个唯一 ID 相关联。这允许您查询日志以找到任何给定请求的匹配响应。
安装
composer require garbetjie/http-request-logger
使用
Laravel 中的传入请求
在 Laravel 中启用请求记录就像将中间件添加到您的 App\Http\Kernel
类的 $middleware
属性一样简单。下面所示的示例足以确保在 Laravel 中记录所有传入请求和传出响应
<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { // ... protected $middleware = [ \Garbetjie\RequestLogging\Http\Middleware\IncomingRequestLoggingMiddleware::class ]; // ... }
注意:您应将请求记录中间件添加到应用程序的全局中间件堆栈中,并在服务提供程序中确定何时进行日志记录。如果将其添加到中间件组中,任何未捕获的异常都会阻止请求和响应的记录。
有关更多信息,请参阅切换启用/禁用部分。
PSR-15 兼容框架中的传入请求
如果您不是使用 Laravel,而是使用遵循 PSR-15 的框架,您在创建中间件时需要更明确一些。下面的示例使用 Slim 框架作为示例
<?php $app = Slim\Factory\AppFactory::create(); $app->add(\Garbetjie\RequestLogging\Http\Middleware\IncomingRequestLoggingMiddleware::class); $app->run();
传入 SOAP 请求
记录传入 SOAP 请求非常简单。只需创建一个 \SoapServer
实例,而是创建一个 \Garbetjie\RequestLogging\Http\SoapServer
的新实例。您可以像使用 \SoapServer
实例一样使用此新实例。以下是一个示例
<?php $monolog = new Monolog\Logger('logger'); $logger = new Garbetjie\RequestLogging\Http\Logger($monolog); $server = new Garbetjie\RequestLogging\Http\SoapServer($logger, '/path/to/wsdl/or/null'); $server->setObject(new stdClass()); $server->handle();;
Laravel 中的传出请求
当使用 Laravel 时,您可以在 Laravel 进行依赖注入的任何地方使用 GuzzleHttp\ClientInterface
或 GuzzleHttp\Client
类型提示。此软件包包含一个服务提供程序,它会自动为您将中间件添加到处理程序堆栈中。
以下是一个在控制器中使用此类型提示的示例
<?php namespace App\Http\Controllers; class MyController { public function myAction(\GuzzleHttp\ClientInterface $client) { return $client->request('GET', 'https://example.org')->getBody()->getContents(); } }
通过 Guzzle 进行传出请求
出站请求日志通过Guzzle中间件处理。为了记录出站请求,只需将一个OutgoingRequestLoggingMiddleware
实例添加到您的处理程序堆栈中。理想情况下,这应该是处理程序堆栈中的最后一个中间件,以确保记录的请求表示尽可能准确。
<?php $monolog = new Monolog\Logger('logger'); $logger = new Garbetjie\RequestLogging\Http\Logger($monolog); $stack = GuzzleHttp\HandlerStack::create(); $stack->push(new Garbetjie\RequestLogging\Http\Middleware\OutgoingRequestLoggingMiddleware($logger)); $client = new GuzzleHttp\Client(['stack' => $stack]); $client->request('GET', 'https://example.org');
出站SOAP请求
为了记录出站SOAP请求,只需像记录任何其他出站HTTP请求一样创建您的Guzzle客户端,并将此客户端实例传递给一个新的Garbetjie\RequestLogging\Http\SoapClient
实例。您可以使用此SOAP客户端实例,就像使用本地的SoapClient
实例一样。
<?php /* @var GuzzleHttp\Client $guzzleClient */ $soapClient = new Garbetjie\RequestLogging\Http\SoapClient($guzzleClient, null, []); $soapResponse = $soapClient->MyCustomSoapMethod(['parameters']);
自定义
请求和响应日志的所有方面都是可定制的。这包括用于将请求和响应链接在一起的ID、日志消息以及与每个请求和响应一起记录的上下文。
日志上下文
默认情况下,入站和出站请求会生成一个类似于以下结构的上下文。敏感的标头,如Authorization
和Cookie
,其值被替换为***
。
<?php $context = [ 'id' => '', // string - contains the unique ID that links this request to its response. 'method' => '', // string - upper-cased request method. 'url' => '', // string - URL to which the request was sent. 'body_length' => 0, // integer - size of the body sent. 'body' => base64_encode(''), // string - base64-encoded body sent in the request. 'headers' => [], // array<string, string> - array of headers sent in the request. Names are normalized and lower-cased. ];
下面的上下文显示了响应日志上下文的默认结构。任何Set-Cookie
标头的值都被移除并替换为***
。
<?php $context = [ 'id' => '', // string - contains the unique ID that links this response to the request that created it. 'duration' => 0.0, // float - the duration of the request, in seconds (with fractional milliseconds). 'status_code' => 0, // integer - the HTTP status code returned in the response. 'body_length' => 0, // integer - the size of the body sent. 'body' => base64_encode(''), // string - base64-encoded body sent in the response. 'headers' => [], // array<string, string> - array of headers sent in the response. Names are normalized and lower-cased. ];
自定义生成的日志上下文相当简单。
<?php $monolog = new Monolog\Logger('name'); $logger = new Garbetjie\RequestLogging\Http\Logger($monolog); $logger->context( function (Garbetjie\RequestLogging\Http\RequestEntry $entry): array { // Return an array containing the context to log. return []; }, function (Garbetjie\RequestLogging\Http\ResponseEntry $entry): array { // Return an array containing the context to log. return []; } );
如果您想简单地扩展默认创建的上下文,可以重用现有的上下文提取器。
<?php $monolog = new Monolog\Logger('name'); $logger = new Garbetjie\RequestLogging\Http\Logger($monolog); $logger->context( function (Garbetjie\RequestLogging\Http\RequestEntry $entry): array { $context = (new Garbetjie\RequestLogging\Http\Context\RequestContext())($entry); $body = base64_decode($context['body']); // Modify $body. $context['body'] = base64_encode($body); return $context; }, null );
ID生成。
默认情况下,用于将请求和响应链接在一起的ID生成是使用endyjasmi/cuid
来生成一个完整的CUID。
可以通过提供一个返回包含要使用ID的字符串的可调用对象来轻松自定义。
<?php $monolog = new Monolog\Logger('name'); $logger = new Garbetjie\RequestLogging\Http\Logger($monolog); $logger->id( function(): string { return base64_encode(random_bytes(8)); } );
切换日志记录
默认情况下,所有请求和响应都会被记录。但是,可以切换是否记录请求或响应。只需提供一个布尔值,或者提供一个返回布尔值的可调用对象,该值表示是否为给定的请求启用日志记录。
<?php $monolog = new Monolog\Logger('name'); $logger = new Garbetjie\RequestLogging\Http\Logger($monolog); function shouldLog($request) { if ($request instanceof Symfony\Component\HttpFoundation\Request) { return stripos($request->getUri(), 'https://example.org') === false; } elseif ($request instanceof Psr\Http\Message\RequestInterface) { return stripos((string)$request->getUri(), 'https://example.org') === false; } else { return false; } } $logger->enabled( function(Garbetjie\RequestLogging\Http\RequestEntry $entry): bool { // Provide a callable that returns a boolean. return shouldLog($entry->request()); }, function(Garbetjie\RequestLogging\Http\ResponseEntry $entry): bool { return shouldLog($entry->request()); } ); // Alternatively: $logger->enabled(false, true); $logger->enabled( new Garbetjie\RequestLogging\Http\Context\RequestContext(), new Garbetjie\RequestLogging\Http\Context\ResponseContext() );
变更日志
有关完整的变更日志,请参阅CHANGELOG.md。