From 3bd355030e7af033bdf7156a9a5c4c0a55d67e95 Mon Sep 17 00:00:00 2001 From: owner888 <4317332+owner888@users.noreply.github.com> Date: Fri, 3 Jul 2026 18:55:08 +0700 Subject: [PATCH 1/2] Expose in-flight Request via 'request' option callback --- src/Client.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Client.php b/src/Client.php index f3db692..e264bfc 100644 --- a/src/Client.php +++ b/src/Client.php @@ -203,6 +203,13 @@ public function process($address): void } $request->setOptions($options)->attachConnection($connection); + // Hand the in-flight Request to the caller (e.g. to close its connection for cancellation). + // Fires again with the new Request when a redirect is followed, so the caller always + // holds the live one. No behavior change unless the 'request' option is set. + if (isset($options['request'])) { + call_user_func($options['request'], $request); + } + $client = $this; $request->once('success', function($response) use ($task, $client, $request) { $client->recycleConnectionFromRequest($request, $response); From a089b53f4d5a75a6e26e9c7e7ca60fe7e7dd3fee Mon Sep 17 00:00:00 2001 From: owner888 <4317332+owner888@users.noreply.github.com> Date: Fri, 3 Jul 2026 23:19:21 +0700 Subject: [PATCH 2/2] Fix keep-alive: HTTP/1.1 is persistent by default (RFC 7230), don't require explicit keep-alive header --- src/Client.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Client.php b/src/Client.php index e264bfc..62e3849 100644 --- a/src/Client.php +++ b/src/Client.php @@ -286,8 +286,16 @@ public function recycleConnectionFromRequest(Request $request, ?Response $respon $connection->onConnect = $connection->onClose = $connection->onMessage = $connection->onError = null; $request_header_connection = strtolower($request->getHeaderLine('Connection')); $response_header_connection = $response ? strtolower($response->getHeaderLine('Connection')) : ''; - // Close Connection without header Connection: keep-alive - if ('keep-alive' !== $request_header_connection || 'keep-alive' !== $response_header_connection || $request->getProtocolVersion() !== '1.1') { + // RFC 7230 §6.3: HTTP/1.1 connections are persistent by default — servers usually OMIT + // the Connection header. Close only when either side explicitly says "close", the + // protocol is not 1.1, or there is no response (transport-level failure). + // (Previously required both sides to literally send "Connection: keep-alive", which + // almost never happens with real-world servers, so the pool never reused connections.) + $shouldClose = !$response + || $request->getProtocolVersion() !== '1.1' + || str_contains($request_header_connection, 'close') + || str_contains($response_header_connection, 'close'); + if ($shouldClose) { $connection->close(); } $request->detachConnection($connection);