From 1a77137f9350ce8e4dcf5b9f46a78311aa45fde0 Mon Sep 17 00:00:00 2001 From: tw Date: Fri, 19 Dec 2025 15:49:56 +0800 Subject: [PATCH 01/13] add http2 request --- src/core/Coroutine/Http2/ChannelManager.php | 60 +++++++ src/core/Coroutine/Http2/Client2.php | 183 ++++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 src/core/Coroutine/Http2/ChannelManager.php create mode 100644 src/core/Coroutine/Http2/Client2.php diff --git a/src/core/Coroutine/Http2/ChannelManager.php b/src/core/Coroutine/Http2/ChannelManager.php new file mode 100644 index 0000000..2b4c0c0 --- /dev/null +++ b/src/core/Coroutine/Http2/ChannelManager.php @@ -0,0 +1,60 @@ +channels[$id])) { + return $this->channels[$id]; + } + + if ($initialize) { + return $this->channels[$id] = $this->make(1); + } + + return null; + } + + public function make(int $limit): Channel + { + return new Channel($limit); + } + + public function close(int $id): void + { + if ($channel = $this->channels[$id] ?? null) { + $channel->close(); + } + + unset($this->channels[$id]); + } + + public function getChannels(): array + { + return $this->channels; + } + + public function flush(): void + { + $channels = $this->getChannels(); + foreach ($channels as $id => $channel) { + $this->close($id); + } + } + + public function isEmpty(): bool + { + return count($this->channels) === 0; + } +} diff --git a/src/core/Coroutine/Http2/Client2.php b/src/core/Coroutine/Http2/Client2.php new file mode 100644 index 0000000..6933492 --- /dev/null +++ b/src/core/Coroutine/Http2/Client2.php @@ -0,0 +1,183 @@ +channelManager = new ChannelManager(); + $this->lastSendTime = time(); + } + + public function request(Request $request, float $timeout = -1): false|Response + { + $this->loop(); + $streamId = $this->send($request); + + if ($streamId === false) { + $this->close(); + return false; + } + $this->lastSendTime = time(); + ++$this->requests; + $manager = $this->getChannelManager(); + $chan = $manager->get($streamId, true); + try { + $data = $chan->pop($timeout); + } finally { + $manager->close($streamId); + } + + return $data; + } + + public function close(): bool + { + $this->getChannelManager()->flush(); + $this->chan?->close(); + $this->chan = null; + $this->sleepChan?->close(); + $this->sleepChan = null; + return parent::close(); + } + + protected function getChannelManager(): ChannelManager + { + return $this->channelManager; + } + + protected function reconnect(): bool + { + parent::close(); + return parent::connect(); + } + + protected function getHeartbeat(): int + { + return 30; + } + + protected function heartbeat(): void + { + $heartbeat = $this->getHeartbeat(); + if (! $this->heartbeat) { + $this->heartbeat = true; + + Coroutine::create( + function () use ($heartbeat) { + try { + while (true) { + try { + $this->sleep($heartbeat); + if (! $this->getChannelManager()->isEmpty()) { + continue; + } + if (! $this->ping()) { + break; + } + } catch (Throwable $exception) { + swoole_error_log(SWOOLE_LOG_ERROR, $exception->getMessage()); + } + } + } catch (Throwable $exception) { + swoole_error_log(SWOOLE_LOG_ERROR, $exception->getMessage()); + } finally { + $this->close(); + } + } + ); + } + } + + protected function loop(): void + { + $this->heartbeat(); + + if ($this->chan !== null) { + return; + } + $this->chan = new Channel(65535); + + if (! $this->ping()) { + $this->reconnect(); + } + Coroutine::create( + function () { + $reason = ''; + try { + $chan = $this->chan; + while (true) { + $response = $this->recv($this->setting['timeout'] ?? 60); + + if ($chan->errCode !== SWOOLE_CHANNEL_OK) { + $reason = 'channel closed.'; + break; + } + + if ($response === false) { + $reason = 'client broken.'; + break; + } + + if ($channel = $this->getChannelManager()->get($response->streamId)) { + $channel->push($response); + } else { + swoole_error_log(SWOOLE_LOG_ERROR, sprintf('Recv channel [%d] does not exists.', $response->streamId)); + } + } + } catch (Throwable $exception) { + swoole_error_log(SWOOLE_LOG_ERROR, (string) $exception); + } finally { + swoole_error_log(SWOOLE_LOG_DEBUG, 'Recv loop broken, wait to restart in next time. The reason is ' . $reason); + $this->close(); + } + } + ); + + Coroutine::create( + function () { + $this->waitClose(); + } + ); + } + + protected function waitClose(): void + { + while (true) { + $this->sleep(5); + if ($this->channelManager->isEmpty() && time() - $this->lastSendTime > 10) { + $this->close(); + return; + } + } + } + + protected function sleep(float $timeout = -1): void + { + $this->sleepChan ??= new Channel(1); + $this->sleepChan->pop($timeout); + } +} From 9adf3cc85b7abc45a1c44556ffa594d2ac04b670 Mon Sep 17 00:00:00 2001 From: tw Date: Fri, 19 Dec 2025 16:42:36 +0800 Subject: [PATCH 02/13] Optimize the code --- src/core/Coroutine/Http2/Client2.php | 45 ++++++++++++++++++---------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/core/Coroutine/Http2/Client2.php b/src/core/Coroutine/Http2/Client2.php index 6933492..16bb258 100644 --- a/src/core/Coroutine/Http2/Client2.php +++ b/src/core/Coroutine/Http2/Client2.php @@ -23,6 +23,8 @@ class Client2 extends Client protected bool $heartbeat = false; + protected bool $waitClose = false; + protected int $lastSendTime = 0; public function __construct(string $host, int $port = 80, bool $open_ssl = false) @@ -82,16 +84,19 @@ protected function getHeartbeat(): int protected function heartbeat(): void { - $heartbeat = $this->getHeartbeat(); if (! $this->heartbeat) { $this->heartbeat = true; Coroutine::create( - function () use ($heartbeat) { + function () { try { while (true) { try { - $this->sleep($heartbeat); + $this->sleep($this->getHeartbeat()); + + if ($this->chan === null) { + return; + } if (! $this->getChannelManager()->isEmpty()) { continue; } @@ -106,6 +111,7 @@ function () use ($heartbeat) { swoole_error_log(SWOOLE_LOG_ERROR, $exception->getMessage()); } finally { $this->close(); + $this->heartbeat = false; } } ); @@ -115,6 +121,7 @@ function () use ($heartbeat) { protected function loop(): void { $this->heartbeat(); + $this->waitClose(); if ($this->chan !== null) { return; @@ -156,22 +163,30 @@ function () { } } ); - - Coroutine::create( - function () { - $this->waitClose(); - } - ); } protected function waitClose(): void { - while (true) { - $this->sleep(5); - if ($this->channelManager->isEmpty() && time() - $this->lastSendTime > 10) { - $this->close(); - return; - } + if (! $this->waitClose) { + $this->waitClose = true; + Coroutine::create( + function () { + try { + while (true) { + $this->sleep(3); + if ($this->chan === null) { + return; + } + if ($this->channelManager->isEmpty() && time() - $this->lastSendTime > 10) { + $this->close(); + return; + } + } + } finally { + $this->waitClose = false; + } + } + ); } } From 670ac6b8d4a8b4486d980337d4369086780a536b Mon Sep 17 00:00:00 2001 From: tw Date: Mon, 22 Dec 2025 08:29:37 +0800 Subject: [PATCH 03/13] Optimize the code --- src/core/Coroutine/Http2/Client2.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/Coroutine/Http2/Client2.php b/src/core/Coroutine/Http2/Client2.php index 16bb258..420f708 100644 --- a/src/core/Coroutine/Http2/Client2.php +++ b/src/core/Coroutine/Http2/Client2.php @@ -95,7 +95,7 @@ function () { $this->sleep($this->getHeartbeat()); if ($this->chan === null) { - return; + break; } if (! $this->getChannelManager()->isEmpty()) { continue; @@ -175,11 +175,11 @@ function () { while (true) { $this->sleep(3); if ($this->chan === null) { - return; + break; } if ($this->channelManager->isEmpty() && time() - $this->lastSendTime > 10) { $this->close(); - return; + break; } } } finally { From 1ec9df05aeb6b7e65e0021a6fe93c1df8f4b1e38 Mon Sep 17 00:00:00 2001 From: tw Date: Mon, 22 Dec 2025 10:22:01 +0800 Subject: [PATCH 04/13] remove heartbeat --- src/core/Coroutine/Http2/Client2.php | 64 ++++++---------------------- 1 file changed, 12 insertions(+), 52 deletions(-) diff --git a/src/core/Coroutine/Http2/Client2.php b/src/core/Coroutine/Http2/Client2.php index 420f708..380a9e3 100644 --- a/src/core/Coroutine/Http2/Client2.php +++ b/src/core/Coroutine/Http2/Client2.php @@ -21,9 +21,7 @@ class Client2 extends Client protected ChannelManager $channelManager; - protected bool $heartbeat = false; - - protected bool $waitClose = false; + protected bool $idleClose = false; protected int $lastSendTime = 0; @@ -31,19 +29,18 @@ public function __construct(string $host, int $port = 80, bool $open_ssl = false { parent::__construct($host, $port, $open_ssl); $this->channelManager = new ChannelManager(); - $this->lastSendTime = time(); } public function request(Request $request, float $timeout = -1): false|Response { $this->loop(); $streamId = $this->send($request); + $this->lastSendTime = time(); if ($streamId === false) { $this->close(); return false; } - $this->lastSendTime = time(); ++$this->requests; $manager = $this->getChannelManager(); $chan = $manager->get($streamId, true); @@ -56,6 +53,11 @@ public function request(Request $request, float $timeout = -1): false|Response return $data; } + public function getRequests(): int + { + return $this->requests; + } + public function close(): bool { $this->getChannelManager()->flush(); @@ -77,51 +79,9 @@ protected function reconnect(): bool return parent::connect(); } - protected function getHeartbeat(): int - { - return 30; - } - - protected function heartbeat(): void - { - if (! $this->heartbeat) { - $this->heartbeat = true; - - Coroutine::create( - function () { - try { - while (true) { - try { - $this->sleep($this->getHeartbeat()); - - if ($this->chan === null) { - break; - } - if (! $this->getChannelManager()->isEmpty()) { - continue; - } - if (! $this->ping()) { - break; - } - } catch (Throwable $exception) { - swoole_error_log(SWOOLE_LOG_ERROR, $exception->getMessage()); - } - } - } catch (Throwable $exception) { - swoole_error_log(SWOOLE_LOG_ERROR, $exception->getMessage()); - } finally { - $this->close(); - $this->heartbeat = false; - } - } - ); - } - } - protected function loop(): void { - $this->heartbeat(); - $this->waitClose(); + $this->idleClose(); if ($this->chan !== null) { return; @@ -165,10 +125,10 @@ function () { ); } - protected function waitClose(): void + protected function idleClose(): void { - if (! $this->waitClose) { - $this->waitClose = true; + if (! $this->idleClose) { + $this->idleClose = true; Coroutine::create( function () { try { @@ -183,7 +143,7 @@ function () { } } } finally { - $this->waitClose = false; + $this->idleClose = false; } } ); From 368c635d78753217af302eb12629d48ed361ea1c Mon Sep 17 00:00:00 2001 From: tw Date: Wed, 24 Dec 2025 09:56:38 +0800 Subject: [PATCH 05/13] remove requests --- src/core/Coroutine/Http2/Client2.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/core/Coroutine/Http2/Client2.php b/src/core/Coroutine/Http2/Client2.php index 380a9e3..8d35c75 100644 --- a/src/core/Coroutine/Http2/Client2.php +++ b/src/core/Coroutine/Http2/Client2.php @@ -17,8 +17,6 @@ class Client2 extends Client protected ?Channel $sleepChan = null; - protected int $requests = 0; - protected ChannelManager $channelManager; protected bool $idleClose = false; @@ -41,7 +39,6 @@ public function request(Request $request, float $timeout = -1): false|Response $this->close(); return false; } - ++$this->requests; $manager = $this->getChannelManager(); $chan = $manager->get($streamId, true); try { @@ -53,11 +50,6 @@ public function request(Request $request, float $timeout = -1): false|Response return $data; } - public function getRequests(): int - { - return $this->requests; - } - public function close(): bool { $this->getChannelManager()->flush(); From 1003c73138953bf210dfffd89603d07536943a23 Mon Sep 17 00:00:00 2001 From: tw Date: Thu, 25 Dec 2025 09:43:29 +0800 Subject: [PATCH 06/13] add init class --- src/__init__.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/__init__.php b/src/__init__.php index 2d6ccc3..fa9fbd6 100644 --- a/src/__init__.php +++ b/src/__init__.php @@ -32,6 +32,9 @@ 'core/Coroutine/Barrier.php', 'core/Coroutine/Http/ClientProxy.php', 'core/Coroutine/Http/functions.php', + # # + 'core/Coroutine/Http2/Client2.php', + 'core/Coroutine/Http2/ChannelManager.php', # # 'core/ConnectionPool.php', 'core/Database/ObjectProxy.php', From 21158ad8dc70d7bc6d1e935b02f224e56fca0ef2 Mon Sep 17 00:00:00 2001 From: tw Date: Thu, 25 Dec 2025 19:27:48 +0800 Subject: [PATCH 07/13] Optimize the code --- src/core/Coroutine/Http2/ChannelManager.php | 19 ++++++++++--------- src/core/Coroutine/Http2/Client2.php | 2 -- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/core/Coroutine/Http2/ChannelManager.php b/src/core/Coroutine/Http2/ChannelManager.php index 2b4c0c0..1f644a3 100644 --- a/src/core/Coroutine/Http2/ChannelManager.php +++ b/src/core/Coroutine/Http2/ChannelManager.php @@ -13,14 +13,14 @@ class ChannelManager */ protected array $channels = []; - public function get(int $id, bool $initialize = false): ?Channel + public function get(int $streamId, bool $initialize = false): ?Channel { - if (isset($this->channels[$id])) { - return $this->channels[$id]; + if (isset($this->channels[$streamId])) { + return $this->channels[$streamId]; } if ($initialize) { - return $this->channels[$id] = $this->make(1); + return $this->channels[$streamId] = $this->make(1); } return null; @@ -31,13 +31,13 @@ public function make(int $limit): Channel return new Channel($limit); } - public function close(int $id): void + public function close(int $streamId): void { - if ($channel = $this->channels[$id] ?? null) { + if ($channel = $this->channels[$streamId] ?? null) { $channel->close(); } - unset($this->channels[$id]); + unset($this->channels[$streamId]); } public function getChannels(): array @@ -48,8 +48,9 @@ public function getChannels(): array public function flush(): void { $channels = $this->getChannels(); - foreach ($channels as $id => $channel) { - $this->close($id); + $streamIds = array_keys($channels); + foreach ($streamIds as $streamId) { + $this->close($streamId); } } diff --git a/src/core/Coroutine/Http2/Client2.php b/src/core/Coroutine/Http2/Client2.php index 8d35c75..ee92ad3 100644 --- a/src/core/Coroutine/Http2/Client2.php +++ b/src/core/Coroutine/Http2/Client2.php @@ -103,8 +103,6 @@ function () { if ($channel = $this->getChannelManager()->get($response->streamId)) { $channel->push($response); - } else { - swoole_error_log(SWOOLE_LOG_ERROR, sprintf('Recv channel [%d] does not exists.', $response->streamId)); } } } catch (Throwable $exception) { From a11a856d9be1773ed280b76fc0b58695729651da Mon Sep 17 00:00:00 2001 From: tw Date: Fri, 26 Dec 2025 11:37:20 +0800 Subject: [PATCH 08/13] added Http2 tests --- .../Coroutine/Http2/ChannelManagerTest.php | 59 +++++++++++++++++++ tests/unit/Coroutine/Http2/Client2Test.php | 57 ++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 tests/unit/Coroutine/Http2/ChannelManagerTest.php create mode 100644 tests/unit/Coroutine/Http2/Client2Test.php diff --git a/tests/unit/Coroutine/Http2/ChannelManagerTest.php b/tests/unit/Coroutine/Http2/ChannelManagerTest.php new file mode 100644 index 0000000..11860ce --- /dev/null +++ b/tests/unit/Coroutine/Http2/ChannelManagerTest.php @@ -0,0 +1,59 @@ +get(1, true); + $this->assertInstanceOf(Channel::class, $chan); + $chan = $manager->get(1); + $this->assertInstanceOf(Channel::class, $chan); + Coroutine::create( + function () use ($chan) { + usleep(10 * 1000); + $chan->push('Hello World.'); + } + ); + + $this->assertSame('Hello World.', $chan->pop()); + $manager->close(1); + $this->assertNull($manager->get(1)); + } + ); + } + + public function testChannelFlush() + { + run( + function () { + $manager = new ChannelManager(); + $manager->get(1, true); + $manager->get(2, true); + $manager->get(4, true); + $manager->get(5, true); + + $this->assertSame(4, count($manager->getChannels())); + $manager->flush(); + $this->assertSame(0, count($manager->getChannels())); + } + ); + } +} diff --git a/tests/unit/Coroutine/Http2/Client2Test.php b/tests/unit/Coroutine/Http2/Client2Test.php new file mode 100644 index 0000000..01a0613 --- /dev/null +++ b/tests/unit/Coroutine/Http2/Client2Test.php @@ -0,0 +1,57 @@ +set([ + 'timeout' => -1, + 'ssl_host_name' => $domain, + ]); + $client->connect(); + for ($i = 1; $i < 30; ++$i) { + Coroutine::create(function () use ($client, $i) { + $req = new Request(); + $req->method = 'POST'; + $req->path = '/post'; + $req->headers = [ + 'host' => '127.0.0.1', + 'user-agent' => 'Chrome/49.0.2587.3', + 'accept' => 'text/html,application/xhtml+xml,application/xml', + 'accept-encoding' => 'gzip', + ]; + $req->data = (string) $i; + $data = $client->request($req); + $result = json_decode($data->data, true); + $this->assertEquals($i, intval($result['data'])); + }); + } + }); + } +} From e0c077353f434bc47b684c56ded4e9463f752e90 Mon Sep 17 00:00:00 2001 From: tw Date: Fri, 26 Dec 2025 11:46:23 +0800 Subject: [PATCH 09/13] Optimize the code --- tests/unit/Coroutine/Http2/Client2Test.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/Coroutine/Http2/Client2Test.php b/tests/unit/Coroutine/Http2/Client2Test.php index 01a0613..199e480 100644 --- a/tests/unit/Coroutine/Http2/Client2Test.php +++ b/tests/unit/Coroutine/Http2/Client2Test.php @@ -49,7 +49,7 @@ public function testRequest(): void $req->data = (string) $i; $data = $client->request($req); $result = json_decode($data->data, true); - $this->assertEquals($i, intval($result['data'])); + $this->assertEquals($i, (int) $result['data']); }); } }); From 8160b3ab839ee5ea68dbd9608195013f03795265 Mon Sep 17 00:00:00 2001 From: tw Date: Fri, 26 Dec 2025 11:51:09 +0800 Subject: [PATCH 10/13] http2 use go --- src/core/Coroutine/Http2/Client2.php | 8 ++++---- tests/unit/Coroutine/Http2/ChannelManagerTest.php | 4 ++-- tests/unit/Coroutine/Http2/Client2Test.php | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/Coroutine/Http2/Client2.php b/src/core/Coroutine/Http2/Client2.php index ee92ad3..8b4850e 100644 --- a/src/core/Coroutine/Http2/Client2.php +++ b/src/core/Coroutine/Http2/Client2.php @@ -4,13 +4,13 @@ namespace Swoole\Coroutine\Http2; -use Swoole\Coroutine; use Swoole\Coroutine\Channel; -use Swoole\Coroutine\Http2\Client; use Swoole\Http2\Request; use Swoole\Http2\Response; use Throwable; +use function Swoole\Coroutine\go; + class Client2 extends Client { protected ?Channel $chan = null; @@ -83,7 +83,7 @@ protected function loop(): void if (! $this->ping()) { $this->reconnect(); } - Coroutine::create( + go( function () { $reason = ''; try { @@ -119,7 +119,7 @@ protected function idleClose(): void { if (! $this->idleClose) { $this->idleClose = true; - Coroutine::create( + go( function () { try { while (true) { diff --git a/tests/unit/Coroutine/Http2/ChannelManagerTest.php b/tests/unit/Coroutine/Http2/ChannelManagerTest.php index 11860ce..27a0f05 100644 --- a/tests/unit/Coroutine/Http2/ChannelManagerTest.php +++ b/tests/unit/Coroutine/Http2/ChannelManagerTest.php @@ -6,9 +6,9 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -use Swoole\Coroutine; use Swoole\Coroutine\Channel; +use function Swoole\Coroutine\go; use function Swoole\Coroutine\run; /** @@ -26,7 +26,7 @@ function () { $this->assertInstanceOf(Channel::class, $chan); $chan = $manager->get(1); $this->assertInstanceOf(Channel::class, $chan); - Coroutine::create( + go( function () use ($chan) { usleep(10 * 1000); $chan->push('Hello World.'); diff --git a/tests/unit/Coroutine/Http2/Client2Test.php b/tests/unit/Coroutine/Http2/Client2Test.php index 199e480..1b8aca0 100644 --- a/tests/unit/Coroutine/Http2/Client2Test.php +++ b/tests/unit/Coroutine/Http2/Client2Test.php @@ -14,9 +14,9 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; -use Swoole\Coroutine; use Swoole\Http2\Request; +use function Swoole\Coroutine\go; use function Swoole\Coroutine\run; /** @@ -36,7 +36,7 @@ public function testRequest(): void ]); $client->connect(); for ($i = 1; $i < 30; ++$i) { - Coroutine::create(function () use ($client, $i) { + go(function () use ($client, $i) { $req = new Request(); $req->method = 'POST'; $req->path = '/post'; From 4358427179f0530306c88259165783a37f0f7d3b Mon Sep 17 00:00:00 2001 From: tw Date: Tue, 30 Dec 2025 17:28:04 +0800 Subject: [PATCH 11/13] Optimize the code --- src/core/Coroutine/Http2/Client2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Coroutine/Http2/Client2.php b/src/core/Coroutine/Http2/Client2.php index 8b4850e..0d9d2a1 100644 --- a/src/core/Coroutine/Http2/Client2.php +++ b/src/core/Coroutine/Http2/Client2.php @@ -91,7 +91,7 @@ function () { while (true) { $response = $this->recv($this->setting['timeout'] ?? 60); - if ($chan->errCode !== SWOOLE_CHANNEL_OK) { + if ($chan?->errCode !== SWOOLE_CHANNEL_OK) { $reason = 'channel closed.'; break; } From cb324030d40e92e0b3b3a71b05bf84b41e299063 Mon Sep 17 00:00:00 2001 From: tw Date: Wed, 14 Jan 2026 20:25:18 +0800 Subject: [PATCH 12/13] remove active close --- src/core/Coroutine/Http2/Client2.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/Coroutine/Http2/Client2.php b/src/core/Coroutine/Http2/Client2.php index 0d9d2a1..64f0ed5 100644 --- a/src/core/Coroutine/Http2/Client2.php +++ b/src/core/Coroutine/Http2/Client2.php @@ -36,7 +36,6 @@ public function request(Request $request, float $timeout = -1): false|Response $this->lastSendTime = time(); if ($streamId === false) { - $this->close(); return false; } $manager = $this->getChannelManager(); From e9ce2fe45c4e1216b406f2fde690adb761ae007f Mon Sep 17 00:00:00 2001 From: tw Date: Thu, 15 Jan 2026 10:30:33 +0800 Subject: [PATCH 13/13] remove timeout --- src/core/Coroutine/Http2/Client2.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Coroutine/Http2/Client2.php b/src/core/Coroutine/Http2/Client2.php index 64f0ed5..79646b1 100644 --- a/src/core/Coroutine/Http2/Client2.php +++ b/src/core/Coroutine/Http2/Client2.php @@ -88,7 +88,7 @@ function () { try { $chan = $this->chan; while (true) { - $response = $this->recv($this->setting['timeout'] ?? 60); + $response = $this->recv(); if ($chan?->errCode !== SWOOLE_CHANNEL_OK) { $reason = 'channel closed.';