8000 [HttpClient] fix getting response content after its destructor throwe… · symfony/symfony@6d1657b · GitHub
[go: up one dir, main page]

Skip to content

Commit 6d1657b

Browse files
[HttpClient] fix getting response content after its destructor throwed an HttpExceptionInterface
1 parent c895a40 commit 6d1657b

File tree

4 files changed

+35
-14
lines changed

4 files changed

+35
-14
lines changed

src/Symfony/Component/HttpClient/Response/CurlResponse.php

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\HttpClient\Chunk\InformationalChunk;
1717
use Symfony\Component\HttpClient\Exception\TransportException;
1818
use Symfony\Component\HttpClient\Internal\CurlClientState;
19+
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
1920
use Symfony\Contracts\HttpClient\ResponseInterface;
2021

2122
/**
@@ -113,7 +114,7 @@ public function __construct(CurlClientState $multi, $ch, array $options = null,
113114
$this->initializer = static function (self $response) {
114115
$waitFor = curl_getinfo($ch = $response->handle, CURLINFO_PRIVATE);
115116

116-
return 'H' === $waitFor[0] || 'D' === $waitFor[0];
117+
return 'H' === $waitFor[0];
117118
};
118119

119120
// Schedule the request in a non-blocking way
@@ -174,17 +175,15 @@ public function __destruct()
174175
return; // Unused pushed response
175176
}
176177

177-
$waitFor = curl_getinfo($this->handle, CURLINFO_PRIVATE);
178-
179-
if ('C' === $waitFor[0] || '_' === $waitFor[0]) {
180-
$this->close();
181-
} elseif ('H' === $waitFor[0]) {
182-
$waitFor[0] = 'D'; // D = destruct
183-
curl_setopt($this->handle, CURLOPT_PRIVATE, $waitFor);
184-
}
185-
178+
$e = null;
186179
$this->doDestruct();
180+
} catch (HttpExceptionInterface $e) {
181+
throw $e;
187182
} finally {
183+
if (null !== $e) {
184+
throw $e;
185+
}
186+
188187
$this->close();
189188

190189
if (!$this->multi->openHandles) {
@@ -304,7 +303,7 @@ private static function parseHeaderLine($ch, string $data, array &$info, array &
304303
{
305304
$waitFor = @curl_getinfo($ch, CURLINFO_PRIVATE) ?: '_0';
306305

307-
if ('H' !== $waitFor[0] && 'D' !== $waitFor[0]) {
306+
if ('H' !== $waitFor[0]) {
308307
return \strlen($data); // Ignore HTTP trailers
309308
}
310309

@@ -370,7 +369,7 @@ private static function parseHeaderLine($ch, string $data, array &$info, array &
370369
// Headers and redirects completed, time to get the response's content
371370
$multi->handlesActivity[$id][] = new FirstChunk();
372371

373-
if ('D' === $waitFor[0] || 'HEAD' === $info['http_method'] || \in_array($statusCode, [204, 304], true)) {
372+
if ('HEAD' === $info['http_method'] || \in_array($statusCode, [204, 304], true)) {
374373
$waitFor = '_0'; // no content expected
375374
$multi->handlesActivity[$id][] = null;
376375
$multi->handlesActivity[$id][] = null;

src/Symfony/Component/HttpClient/Response/NativeResponse.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\HttpClient\Chunk\FirstChunk;
1616
use Symfony\Component\HttpClient\Exception\TransportException;
1717
use Symfony\Component\HttpClient\Internal\NativeClientState;
18+
use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface;
1819
use Symfony\Contracts\HttpClient\ResponseInterface;
1920

2021
/**
@@ -84,11 +85,16 @@ public function getInfo(string $type = null)
8485

8586
public function __destruct()
8687
{
87-
$this->shouldBuffer = null;
88-
8988
try {
89+
$e = null;
9090
$this->doDestruct();
91+
} catch (HttpExceptionInterface $e) {
92+
throw $e;
9193
} finally {
94+
if (null !== $e) {
95+
throw $e;
96+
}
97+
9298
$this->close();
9399

94100
// Clear the DNS cache when all requests completed

src/Symfony/Component/HttpClient/Response/ResponseTrait.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ private function checkStatusCode()
294294
*/
295295
private function doDestruct()
296296
{
297+
$this->shouldBuffer = true;
298+
297299
if ($this->initializer && null === $this->info['error']) {
298300
self::initialize($this);
299301
$this->checkStatusCode();

src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,20 @@ public function testDestruct()
782782
$this->assertLessThan(4, $duration);
783783
}
784784

785+
public function testGetContentAfterDestruct()
786+
{
787+
$client = $this->getHttpClient(__FUNCTION__);
788+
789+
$start = microtime(true);
790+
791+
try {
792+
$client->request('GET', 'http://localhost:8057/404');
793+
$this->fail(ClientExceptionInterface::class.' expected');
794+
} catch (ClientExceptionInterface $e) {
795+
$this->assertSame('GET', $e->getResponse()->toArray(false)['REQUEST_METHOD']);
796+
}
797+
}
798+
785799
public function testProxy()
786800
{
787801
$client = $this->getHttpClient(__FUNCTION__);

0 commit comments

Comments
 (0)
0