From 684421f5d09afaaa0dc1c896f9d17244544a39d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Tue, 18 Apr 2023 21:04:41 +0200 Subject: [PATCH] Enable HTTP keep-alive by default for HTTP client --- src/Browser.php | 1 - tests/BrowserTest.php | 2 -- tests/FunctionalBrowserTest.php | 53 ++++++++++++++++++++++++++++++--- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/Browser.php b/src/Browser.php index ad9187a6..b7bf4425 100644 --- a/src/Browser.php +++ b/src/Browser.php @@ -23,7 +23,6 @@ class Browser private $baseUrl; private $protocolVersion = '1.1'; private $defaultHeaders = array( - 'Connection' => 'close', 'User-Agent' => 'ReactPHP/1' ); diff --git a/tests/BrowserTest.php b/tests/BrowserTest.php index d01de9c5..b7958016 100644 --- a/tests/BrowserTest.php +++ b/tests/BrowserTest.php @@ -556,8 +556,6 @@ public function testWithMultipleHeadersShouldBeMergedCorrectlyWithMultipleDefaul 'user-Agent' => array('ABC'), 'another-header' => array('value'), 'custom-header' => array('data'), - - 'Connection' => array('close') ); $that->assertEquals($expectedHeaders, $request->getHeaders()); diff --git a/tests/FunctionalBrowserTest.php b/tests/FunctionalBrowserTest.php index 7ab909de..35b96eb6 100644 --- a/tests/FunctionalBrowserTest.php +++ b/tests/FunctionalBrowserTest.php @@ -553,7 +553,7 @@ public function testReceiveStreamAndExplicitlyCloseConnectionEvenWhenServerKeeps $socket->close(); } - public function testRequestWillCreateNewConnectionForSecondRequestByDefaultEvenWhenServerKeepsConnectionOpen() + public function testRequestWithConnectionCloseHeaderWillCreateNewConnectionForSecondRequestEvenWhenServerKeepsConnectionOpen() { $twice = $this->expectCallableOnce(); $socket = new SocketServer('127.0.0.1:0'); @@ -570,6 +570,9 @@ public function testRequestWillCreateNewConnectionForSecondRequestByDefaultEvenW $this->base = str_replace('tcp:', 'http:', $socket->getAddress()) . '/'; + // add `Connection: close` request header to disable HTTP keep-alive + $this->browser = $this->browser->withHeader('Connection', 'close'); + $response = \React\Async\await($this->browser->get($this->base . 'get')); assert($response instanceof ResponseInterface); $this->assertEquals('hello', (string)$response->getBody()); @@ -579,12 +582,54 @@ public function testRequestWillCreateNewConnectionForSecondRequestByDefaultEvenW $this->assertEquals('hello', (string)$response->getBody()); } - public function testRequestWithoutConnectionHeaderWillReuseExistingConnectionForSecondRequest() + public function testRequestWithHttp10WillCreateNewConnectionForSecondRequestEvenWhenServerKeepsConnectionOpen() + { + $twice = $this->expectCallableOnce(); + $socket = new SocketServer('127.0.0.1:0'); + $socket->on('connection', function (\React\Socket\ConnectionInterface $connection) use ($socket, $twice) { + $connection->on('data', function () use ($connection) { + $connection->write("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello"); + }); + + $socket->on('connection', $twice); + $socket->on('connection', function () use ($socket) { + $socket->close(); + }); + }); + + $this->base = str_replace('tcp:', 'http:', $socket->getAddress()) . '/'; + + // use HTTP/1.0 to disable HTTP keep-alive + $this->browser = $this->browser->withProtocolVersion('1.0'); + + $response = \React\Async\await($this->browser->get($this->base . 'get')); + assert($response instanceof ResponseInterface); + $this->assertEquals('hello', (string)$response->getBody()); + + $response = \React\Async\await($this->browser->get($this->base . 'get')); + assert($response instanceof ResponseInterface); + $this->assertEquals('hello', (string)$response->getBody()); + } + + public function testRequestWillReuseExistingConnectionForSecondRequestByDefault() { $this->socket->on('connection', $this->expectCallableOnce()); - // remove default `Connection: close` request header to enable keep-alive - $this->browser = $this->browser->withoutHeader('Connection'); + $response = \React\Async\await($this->browser->get($this->base . 'get')); + assert($response instanceof ResponseInterface); + $this->assertEquals('hello', (string)$response->getBody()); + + $response = \React\Async\await($this->browser->get($this->base . 'get')); + assert($response instanceof ResponseInterface); + $this->assertEquals('hello', (string)$response->getBody()); + } + + public function testRequestWithHttp10AndConnectionKeepAliveHeaderWillReuseExistingConnectionForSecondRequest() + { + $this->socket->on('connection', $this->expectCallableOnce()); + + $this->browser = $this->browser->withProtocolVersion('1.0'); + $this->browser = $this->browser->withHeader('Connection', 'keep-alive'); $response = \React\Async\await($this->browser->get($this->base . 'get')); assert($response instanceof ResponseInterface);