diff --git a/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php b/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php index a731f83fe2..7a60bdd435 100644 --- a/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php +++ b/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php @@ -119,7 +119,7 @@ final class HttpClientDataCollector extends DataCollector implements LateDataCol unset($info['http_method']); } - if ($trace['url'] === $info['url']) { + if (($info['url'] ?? null) === $trace['url']) { unset($info['url']); } diff --git a/src/Symfony/Component/HttpClient/Response/CurlResponse.php b/src/Symfony/Component/HttpClient/Response/CurlResponse.php index c497cfc4fd..0a6597fb08 100644 --- a/src/Symfony/Component/HttpClient/Response/CurlResponse.php +++ b/src/Symfony/Component/HttpClient/Response/CurlResponse.php @@ -16,6 +16,7 @@ use Symfony\Component\HttpClient\Chunk\FirstChunk; use Symfony\Component\HttpClient\Chunk\InformationalChunk; use Symfony\Component\HttpClient\Exception\TransportException; use Symfony\Component\HttpClient\Internal\CurlClientState; +use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface; use Symfony\Contracts\HttpClient\ResponseInterface; /** @@ -113,7 +114,7 @@ final class CurlResponse implements ResponseInterface $this->initializer = static function (self $response) { $waitFor = curl_getinfo($ch = $response->handle, CURLINFO_PRIVATE); - return 'H' === $waitFor[0] || 'D' === $waitFor[0]; + return 'H' === $waitFor[0]; }; // Schedule the request in a non-blocking way @@ -174,17 +175,15 @@ final class CurlResponse implements ResponseInterface return; // Unused pushed response } - $waitFor = curl_getinfo($this->handle, CURLINFO_PRIVATE); - - if ('C' === $waitFor[0] || '_' === $waitFor[0]) { - $this->close(); - } elseif ('H' === $waitFor[0]) { - $waitFor[0] = 'D'; // D = destruct - curl_setopt($this->handle, CURLOPT_PRIVATE, $waitFor); + $e = null; + $this->doDestruct(); + } catch (HttpExceptionInterface $e) { + throw $e; + } finally { + if ($e ?? false) { + throw $e; } - $this->doDestruct(); - } finally { $this->close(); if (!$this->multi->openHandles) { @@ -304,7 +303,7 @@ final class CurlResponse implements ResponseInterface { $waitFor = @curl_getinfo($ch, CURLINFO_PRIVATE) ?: '_0'; - if ('H' !== $waitFor[0] && 'D' !== $waitFor[0]) { + if ('H' !== $waitFor[0]) { return \strlen($data); // Ignore HTTP trailers } @@ -370,7 +369,7 @@ final class CurlResponse implements ResponseInterface // Headers and redirects completed, time to get the response's content $multi->handlesActivity[$id][] = new FirstChunk(); - if ('D' === $waitFor[0] || 'HEAD' === $info['http_method'] || \in_array($statusCode, [204, 304], true)) { + if ('HEAD' === $info['http_method'] || \in_array($statusCode, [204, 304], true)) { $waitFor = '_0'; // no content expected $multi->handlesActivity[$id][] = null; $multi->handlesActivity[$id][] = null; diff --git a/src/Symfony/Component/HttpClient/Response/NativeResponse.php b/src/Symfony/Component/HttpClient/Response/NativeResponse.php index 7abe18abab..6fccfbef5a 100644 --- a/src/Symfony/Component/HttpClient/Response/NativeResponse.php +++ b/src/Symfony/Component/HttpClient/Response/NativeResponse.php @@ -15,6 +15,7 @@ use Psr\Log\LoggerInterface; use Symfony\Component\HttpClient\Chunk\FirstChunk; use Symfony\Component\HttpClient\Exception\TransportException; use Symfony\Component\HttpClient\Internal\NativeClientState; +use Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface; use Symfony\Contracts\HttpClient\ResponseInterface; /** @@ -84,11 +85,16 @@ final class NativeResponse implements ResponseInterface public function __destruct() { - $this->shouldBuffer = null; - try { + $e = null; $this->doDestruct(); + } catch (HttpExceptionInterface $e) { + throw $e; } finally { + if ($e ?? false) { + throw $e; + } + $this->close(); // Clear the DNS cache when all requests completed diff --git a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php index 8793a45184..000da5344d 100644 --- a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php +++ b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php @@ -294,6 +294,8 @@ trait ResponseTrait */ private function doDestruct() { + $this->shouldBuffer = true; + if ($this->initializer && null === $this->info['error']) { self::initialize($this); $this->checkStatusCode(); diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/composer.json b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/composer.json index 8515a1b775..a6758c1300 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/composer.json +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/composer.json @@ -18,7 +18,8 @@ "require": { "php": "^7.2.5", "symfony/http-client": "^4.3|5.0", - "symfony/messenger": "^4.3|^5.0" + "symfony/messenger": "^4.3|^5.0", + "symfony/service-contracts": "^1.1|^2" }, "require-dev": { "symfony/http-client-contracts": "^1.0|^2.0", diff --git a/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php b/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php index 7bc174f05c..b45c948acd 100644 --- a/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php +++ b/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Security\Core\Exception; /** - * AuthenticationServiceException is thrown when an authenticated token becomes un-authenticated between requests. + * AuthenticationExpiredException is thrown when an authenticated token becomes un-authenticated between requests. * * In practice, this is due to the User changing between requests (e.g. password changes), * causes the token to become un-authenticated. diff --git a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php index 99704b3e75..05d1e77e50 100644 --- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php @@ -86,7 +86,7 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface return $token; } - // this AccountStatusException causes the user to be logged out + // this AccountExpiredException causes the user to be logged out throw new AuthenticationExpiredException(); } diff --git a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php index aad712e3e8..de13686819 100644 --- a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php +++ b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php @@ -782,6 +782,18 @@ abstract class HttpClientTestCase extends TestCase $this->assertLessThan(4, $duration); } + public function testGetContentAfterDestruct() + { + $client = $this->getHttpClient(__FUNCTION__); + + try { + $client->request('GET', 'http://localhost:8057/404'); + $this->fail(ClientExceptionInterface::class.' expected'); + } catch (ClientExceptionInterface $e) { + $this->assertSame('GET', $e->getResponse()->toArray(false)['REQUEST_METHOD']); + } + } + public function testProxy() { $client = $this->getHttpClient(__FUNCTION__);