From 369937bd63f56182a13d67d15b84a933829c6e2d Mon Sep 17 00:00:00 2001 From: Maxime Veber Date: Sat, 27 Apr 2024 01:36:34 +0200 Subject: [PATCH] Add inactivity timeout to TO interceptor --- README.md | 1 + src/Interceptor/SetRequestTimeout.php | 8 ++++++- test/TimeoutTest.php | 33 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 161b8490..c2eba0af 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,7 @@ The big disadvantage of network interceptors is that they have to be rather quic - `SetRequestHeaderIfUnset` - `SetResponseHeader` - `SetResponseHeaderIfUnset` +- `SetRequestTimeout` - [`CookieHandler`](https://github.com/amphp/http-client-cookies) - [`PrivateCache`](https://github.com/amphp/http-client-cache) diff --git a/src/Interceptor/SetRequestTimeout.php b/src/Interceptor/SetRequestTimeout.php index e263d251..6c3eecbd 100644 --- a/src/Interceptor/SetRequestTimeout.php +++ b/src/Interceptor/SetRequestTimeout.php @@ -10,16 +10,22 @@ public function __construct( float $tcpConnectTimeout = 10, float $tlsHandshakeTimeout = 10, float $transferTimeout = 10, + float $inactivityTimeout = null, ) { parent::__construct(static function (Request $request) use ( $tcpConnectTimeout, $tlsHandshakeTimeout, - $transferTimeout + $transferTimeout, + $inactivityTimeout ) { $request->setTcpConnectTimeout($tcpConnectTimeout); $request->setTlsHandshakeTimeout($tlsHandshakeTimeout); $request->setTransferTimeout($transferTimeout); + if (null !== $inactivityTimeout) { + $request->setInactivityTimeout($inactivityTimeout); + } + return $request; }); } diff --git a/test/TimeoutTest.php b/test/TimeoutTest.php index 50883106..a26aefcb 100644 --- a/test/TimeoutTest.php +++ b/test/TimeoutTest.php @@ -242,4 +242,37 @@ public function testTimeoutDuringTlsEnableInterceptor(): void $server->close(); } } + + public function testTimeoutDuringInactivity(): void + { + $server = listen("tcp://127.0.0.1:0"); + + EventLoop::queue(static function () use ($server): void { + while ($client = $server->accept()) { + $client->write("HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\n."); + + EventLoop::unreference(EventLoop::delay(3, static function () use ($client): void { + $client->close(); + })); + } + }); + + $this->setTimeout(2); + + try { + $uri = "http://" . $server->getAddress() . "/"; + + $request = new Request($uri); + + $client = new InterceptedHttpClient(new PooledHttpClient, new SetRequestTimeout(10, 10, 10, 1), []); + $response = $client->request($request, new NullCancellation); + + $this->expectException(StreamException::class); + $this->expectExceptionMessage("HTTP response did not complete: Inactivity timeout exceeded, more than 1 seconds elapsed from last data received"); + + $response->getBody()->buffer(); + } finally { + $server->close(); + } + } }