From 0fc371e7df60be9a820081b414469ddedf93a3c6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 25 Oct 2019 08:37:36 +0200 Subject: [PATCH] [HttpClient] ignore the body of responses to HEAD requests --- .../Component/HttpClient/CurlHttpClient.php | 2 ++ .../HttpClient/Response/MockResponse.php | 2 +- .../HttpClient/Response/NativeResponse.php | 10 ++++++- .../HttpClient/Test/HttpClientTestCase.php | 27 +++++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpClient/CurlHttpClient.php b/src/Symfony/Component/HttpClient/CurlHttpClient.php index 471f694b4e89..56a129783d48 100644 --- a/src/Symfony/Component/HttpClient/CurlHttpClient.php +++ b/src/Symfony/Component/HttpClient/CurlHttpClient.php @@ -197,6 +197,8 @@ public function request(string $method, string $url, array $options = []): Respo 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; } diff --git a/src/Symfony/Component/HttpClient/Response/MockResponse.php b/src/Symfony/Component/HttpClient/Response/MockResponse.php index fa8abebea447..3b961db4d13f 100644 --- a/src/Symfony/Component/HttpClient/Response/MockResponse.php +++ b/src/Symfony/Component/HttpClient/Response/MockResponse.php @@ -176,7 +176,7 @@ protected static function perform(ClientState $multi, array &$responses): void try { $offset = 0; $chunk[1]->getStatusCode(); - $response->headers = $chunk[1]->getHeaders(false); + $chunk[1]->getHeaders(false); self::readResponse($response, $chunk[0], $chunk[1], $offset); $multi->handlesActivity[$id][] = new FirstChunk(); } catch (\Throwable $e) { diff --git a/src/Symfony/Component/HttpClient/Response/NativeResponse.php b/src/Symfony/Component/HttpClient/Response/NativeResponse.php index 2f414e3ba2d1..3115bade504d 100644 --- a/src/Symfony/Component/HttpClient/Response/NativeResponse.php +++ b/src/Symfony/Component/HttpClient/Response/NativeResponse.php @@ -174,8 +174,16 @@ private function open(): void $this->inflate = null; } - $this->multi->openHandles[$this->id] = [$h, $this->buffer, $this->inflate, $this->content, $this->onProgress, &$this->remaining, &$this->info]; $this->multi->handlesActivity[$this->id] = [new FirstChunk()]; + + if ('HEAD' === $context['http']['method']) { + $this->multi->handlesActivity[$this->id][] = null; + $this->multi->handlesActivity[$this->id][] = null; + + return; + } + + $this->multi->openHandles[$this->id] = [$h, $this->buffer, $this->inflate, $this->content, $this->onProgress, &$this->remaining, &$this->info]; } /** diff --git a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php index 485712c6888a..78d0f1b39c25 100644 --- a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php +++ b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php @@ -72,6 +72,33 @@ public function testGetRequest() $response->getContent(); } + public function testHeadRequest() + { + $client = $this->getHttpClient(__FUNCTION__); + $response = $client->request('HEAD', 'http://localhost:8057', [ + 'headers' => ['Foo' => 'baR'], + 'user_data' => $data = new \stdClass(), + ]); + + $this->assertSame([], $response->getInfo('response_headers')); + $this->assertSame($data, $response->getInfo()['user_data']); + $this->assertSame(200, $response->getStatusCode()); + + $info = $response->getInfo(); + $this->assertNull($info['error']); + $this->assertSame(0, $info['redirect_count']); + $this->assertSame('HTTP/1.1 200 OK', $info['response_headers'][0]); + $this->assertSame('Host: localhost:8057', $info['response_headers'][1]); + $this->assertSame('http://localhost:8057/', $info['url']); + + $headers = $response->getHeaders(); + + $this->assertSame('localhost:8057', $headers['host'][0]); + $this->assertSame(['application/json'], $headers['content-type']); + + $this->assertSame('', $response->getContent()); + } + public function testNonBufferedGetRequest() { $client = $this->getHttpClient(__FUNCTION__);