请问如何监听GuzzleHttp的请求?
1. 运行环境
1). 当前使用的 Laravel 版本?
目前使用的是laravel9.33
2). 当前使用的 php/php-fpm 版本?
php使用的是8.1.19
php-fpm 版本:
3). 当前系统
4). 业务环境
5). 相关软件版本
2. 问题描述?
我在开发一个日志系统,需要捕获到项目里对外的http请求,目前项目中使用的是一个guzzlehttp的fork版本。
我本地尝试了一下,如果是通过Illuminate\Support\Facades\Http对象发起的get/post请求,那么可以通过监听laravel的Illuminate\Http\Client\Events\RequestSending事件来获取我想要的数据。
但是项目中都是通过
Http::baseUrl($this->baseUriVia())->timeout($this->timeoutVia())->setClient(new Client())获取client对象。
然后这个Client类,继承了guzzlehttpclient, class Client extends GuzzleHttpClient,在构造函数里做了一些定制化,然后parent::__construct($config)。
我发现通过这种方式发起的get/post请求,无法通过监听那个事件得到结果,也就是没有触发那个事件,现在很困扰,不知道该如何才能监听到。
可类似封装一个,在中间件中记录日志,当然这个是指有良好的架构前提先进行的
我们是在guzzle 类上包了一层,然后在里面做的日志
GuzzleHttp 的自带的 Middleware 就可以实现:
更多功能参考官方文档:docs.guzzlephp.org/en/stable/handl...
github.com/huzaifaarain/telescope-... 了解下
我明白OP希望在各个业务方不改动源码的情况下,监听RequestSending事件,那么让我们看看RequestSending事件是在哪里发出的,在laravel项目中全局搜索RequestSending方法,你会找到一个:
$pendingRequest->dispatchRequestSendingEvent();
的调用,这个调用被丢进了PendingRequest的beforeSendingCallbacks属性里面,作为request真正发起前的回调,那我们再找找这个beforeSendingCallbacks
在哪里被使用了呢?跟踪这个属性,会发现他在一个beforeSendingCallbacks
的方法里被调用了,一路往上跟踪,你会发现,这个方法最终会在buildClient时,作为client的handlerStack传入,至于handlerStack是什么,楼上已经有人给出解释了。事已至此,那么你就应该明白了,在不对Client干预的情况下,它压根不会发出事件,那么你无论如何努力也做不到了。那么,在这种情况下,到底有没有办法能做到这个事情呢?其实也不是完全没有办法,PendingReuqest这个类,在laravel的Http Facade里面是写死的,所以你没办法配置它,但是你可以patch它,你写一个composer包,把PendingRequest类的内容拷贝一份出来,修改他的buildClient的方法,在它返回你们自己的client时,应用上对应的handlerStack(当然这里面有很多细节要处理),然后在vendor publish的时候,覆盖掉
vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php
即可。以上内容仅是我个人摸鱼时间查看源码得出的理论方案,并未实践验证,具体是否可行可以写代码自行验证。
GuzzleHttp可以添加自带的日志记录中间件 Middleware::log()
我也同意上面提到的中间价。正常情况下你们的client 应该复用。你们的demo貌似多次new client ,所以出现这个问题。