From f4f6d813fa3730d3f4fc4e18f6ca3d67032c7282 Mon Sep 17 00:00:00 2001 From: Kurt Thiemann Date: Mon, 2 Dec 2024 12:18:11 +0100 Subject: [PATCH 1/2] [HttpClient] Always set CURLOPT_CUSTOMREQUEST to the correct HTTP method in CurlHttpClient --- CurlHttpClient.php | 3 +-- Tests/HttpClientTestCase.php | 22 ++++++++++++++++++++++ composer.json | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/CurlHttpClient.php b/CurlHttpClient.php index 7d99620..3e15bef 100644 --- a/CurlHttpClient.php +++ b/CurlHttpClient.php @@ -197,13 +197,12 @@ public function request(string $method, string $url, array $options = []): Respo $curlopts[\CURLOPT_RESOLVE] = $resolve; } + $curlopts[\CURLOPT_CUSTOMREQUEST] = $method; if ('POST' === $method) { // Use CURLOPT_POST to have browser-like POST-to-GET redirects for 301, 302 and 303 $curlopts[\CURLOPT_POST] = true; } elseif ('HEAD' === $method) { $curlopts[\CURLOPT_NOBODY] = true; - } else { - $curlopts[\CURLOPT_CUSTOMREQUEST] = $method; } if ('\\' !== \DIRECTORY_SEPARATOR && $options['timeout'] < 1) { diff --git a/Tests/HttpClientTestCase.php b/Tests/HttpClientTestCase.php index a0e57bf..f572908 100644 --- a/Tests/HttpClientTestCase.php +++ b/Tests/HttpClientTestCase.php @@ -651,4 +651,26 @@ public function testDefaultContentType() $this->assertSame(['abc' => 'def', 'content-type' => 'application/json', 'REQUEST_METHOD' => 'POST'], $response->toArray()); } + + public function testHeadRequestWithClosureBody() + { + $p = TestHttpServer::start(8067); + + try { + $client = $this->getHttpClient(__FUNCTION__); + + $response = $client->request('HEAD', 'http://localhost:8057/head', [ + 'body' => fn () => '', + ]); + $headers = $response->getHeaders(); + } finally { + $p->stop(); + } + + $this->assertArrayHasKey('x-request-vars', $headers); + + $vars = json_decode($headers['x-request-vars'][0], true); + $this->assertIsArray($vars); + $this->assertSame('HEAD', $vars['REQUEST_METHOD']); + } } diff --git a/composer.json b/composer.json index 23437d5..9c9ee14 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "php": ">=8.1", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "~3.4.3|^3.5.1", + "symfony/http-client-contracts": "~3.4.4|^3.5.2", "symfony/service-contracts": "^2.5|^3" }, "require-dev": { From c40cbac81f334e56c21bc54e78115770cf8defd6 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Thu, 5 Dec 2024 00:17:16 +0100 Subject: [PATCH 2/2] chore: fix CS --- Response/CurlResponse.php | 2 +- Tests/CurlHttpClientTest.php | 1 + Tests/NoPrivateNetworkHttpClientTest.php | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Response/CurlResponse.php b/Response/CurlResponse.php index 55c4240..119e201 100644 --- a/Response/CurlResponse.php +++ b/Response/CurlResponse.php @@ -316,7 +316,7 @@ private static function perform(ClientState $multi, ?array &$responses = null): } $multi->handlesActivity[$id][] = null; - $multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) || '_0' === $waitFor || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) || (curl_error($ch) === 'OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 0' && -1.0 === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) && \in_array('close', array_map('strtolower', $responses[$id]->headers['connection']), true)) ? null : new TransportException(ucfirst(curl_error($ch) ?: curl_strerror($result)).\sprintf(' for "%s".', curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL))); + $multi->handlesActivity[$id][] = \in_array($result, [\CURLE_OK, \CURLE_TOO_MANY_REDIRECTS], true) || '_0' === $waitFor || curl_getinfo($ch, \CURLINFO_SIZE_DOWNLOAD) === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) || ('OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 0' === curl_error($ch) && -1.0 === curl_getinfo($ch, \CURLINFO_CONTENT_LENGTH_DOWNLOAD) && \in_array('close', array_map('strtolower', $responses[$id]->headers['connection']), true)) ? null : new TransportException(ucfirst(curl_error($ch) ?: curl_strerror($result)).\sprintf(' for "%s".', curl_getinfo($ch, \CURLINFO_EFFECTIVE_URL))); } } finally { $multi->performing = false; diff --git a/Tests/CurlHttpClientTest.php b/Tests/CurlHttpClientTest.php index 1a30f16..a18b253 100644 --- a/Tests/CurlHttpClientTest.php +++ b/Tests/CurlHttpClientTest.php @@ -17,6 +17,7 @@ /** * @requires extension curl + * * @group dns-sensitive */ class CurlHttpClientTest extends HttpClientTestCase diff --git a/Tests/NoPrivateNetworkHttpClientTest.php b/Tests/NoPrivateNetworkHttpClientTest.php index 181b7f4..c160dff 100644 --- a/Tests/NoPrivateNetworkHttpClientTest.php +++ b/Tests/NoPrivateNetworkHttpClientTest.php @@ -68,6 +68,7 @@ public static function getExcludeHostData(): iterable /** * @dataProvider getExcludeIpData + * * @group dns-sensitive */ public function testExcludeByIp(string $ipAddr, $subnets, bool $mustThrow) @@ -105,6 +106,7 @@ public function testExcludeByIp(string $ipAddr, $subnets, bool $mustThrow) /** * @dataProvider getExcludeHostData + * * @group dns-sensitive */ public function testExcludeByHost(string $ipAddr, $subnets, bool $mustThrow)