我有一个 DiscordPHP 机器人,我正在尝试下载一些需要 cookie 的网页。看来我需要将curl处理程序与Guzzle一起使用,因为ReactPHP http浏览器不支持cookie。
我创建了这个最小的脚本:
use GuzzleHttp\Client; use GuzzleHttp\Handler\CurlMultiHandler; use GuzzleHttp\HandlerStack; use Psr\Http\Message\ResponseInterface; include 'vendor/autoload.php'; $loop = \React\EventLoop\Loop::get(); $curl = new CurlMultiHandler; $handler = HandlerStack::create($curl); $client = new Client( [ /* 'cookies' => $cookieJar, */ 'handler' => $handler ] ); $promise = $client->getAsync('https://httpstat.us/200') ->then( function (ResponseInterface $res) { echo 'response: ' . $res->getStatusCode() . PHP_EOL; }, function (\Exception $e) { echo $e->getMessage() . PHP_EOL; } ); $timer = $loop->addPeriodicTimer(0.5, function () use ($curl, $promise) { if ($promise->getState() === 'pending') { echo 'Tick '; $curl->tick(); } echo 'Beat '; }); $loop->run();
这会立即退出,而无需添加 addPeriodicTimer
来检查挂起并手动调用 tick()
的代码:
$ time php minimal.php 0.022u 0.010s 0:00.03 100.0% 0+0k 0+0io 67pf+0w
使用计时器,它按预期工作:
Tick Beat Tick Beat Tick Beat Tick Beat Tick Beat Tick Beat Tick response: 200 Beat Beat Beat ...
使用 tick()
的想法来自 github.com 上的这个 73 条评论的封闭线程。
有一些类似的问题,但似乎都没有解决这个问题:
wait()
这是一个阻塞调用。sleep()
调用,ReactPHP 真的是异步的吗?执行一个长 for
循环。两者都阻塞了循环。如何使用 cookie jar 启动 HTTP GET
并在 ReactPHP 事件循环中获取响应,而不使用阻塞调用(例如 ->wait()
或手动 tick()
ing curl 的处理程序?强>
P粉3843669232024-02-18 11:41:28
嗯,ReactPHP 不会自动设置 cookie,已经有一个讨论此主题的票证: https ://github.com/reactphp/http/issues/445,但您仍然可以手动方式设置 HTTP cookie 标头。
还值得一提的是,将 ReactPHP 与 Guzzle 一起使用将不起作用,因为 Guzzle 会阻止 ReactPHP 的事件循环。这意味着您可以发送多个请求,但不能异步执行任何其他操作。