From bbb8ed11ff20bf9dad9918cf176762b8e45a2762 Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Mon, 21 Oct 2019 10:45:40 +0200 Subject: [PATCH] [HttpClient] Add a canceled state to the ResponseInterface --- src/Symfony/Component/HttpClient/CHANGELOG.md | 1 + .../Component/HttpClient/NativeHttpClient.php | 1 + .../HttpClient/Response/MockResponse.php | 1 + .../HttpClient/Response/ResponseTrait.php | 2 ++ .../HttpClient/Tests/MockHttpClientTest.php | 1 + .../HttpClient/ResponseInterface.php | 19 ++++++++++--------- .../HttpClient/Test/HttpClientTestCase.php | 11 +++++++++++ 7 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/HttpClient/CHANGELOG.md b/src/Symfony/Component/HttpClient/CHANGELOG.md index bddd592b3b..a116ff72ec 100644 --- a/src/Symfony/Component/HttpClient/CHANGELOG.md +++ b/src/Symfony/Component/HttpClient/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 4.4.0 ----- + * added `canceled` to `ResponseInterface::getInfo()` * added `HttpClient::createForBaseUri()` * added `HttplugClient` with support for sync and async requests * added `max_duration` option diff --git a/src/Symfony/Component/HttpClient/NativeHttpClient.php b/src/Symfony/Component/HttpClient/NativeHttpClient.php index fcafffaf59..b86b7c84eb 100644 --- a/src/Symfony/Component/HttpClient/NativeHttpClient.php +++ b/src/Symfony/Component/HttpClient/NativeHttpClient.php @@ -96,6 +96,7 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac 'response_headers' => [], 'url' => $url, 'error' => null, + 'canceled' => false, 'http_method' => $method, 'http_code' => 0, 'redirect_count' => 0, diff --git a/src/Symfony/Component/HttpClient/Response/MockResponse.php b/src/Symfony/Component/HttpClient/Response/MockResponse.php index 4c5c322c1b..59db21cc3f 100644 --- a/src/Symfony/Component/HttpClient/Response/MockResponse.php +++ b/src/Symfony/Component/HttpClient/Response/MockResponse.php @@ -84,6 +84,7 @@ class MockResponse implements ResponseInterface */ public function cancel(): void { + $this->info['canceled'] = true; $this->info['error'] = 'Response has been canceled.'; $this->body = null; } diff --git a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php index d27acfa550..4cd7710f78 100644 --- a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php +++ b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php @@ -52,6 +52,7 @@ trait ResponseTrait 'response_headers' => [], 'http_code' => 0, 'error' => null, + 'canceled' => false, ]; /** @var resource */ @@ -178,6 +179,7 @@ trait ResponseTrait */ public function cancel(): void { + $this->info['canceled'] = true; $this->info['error'] = 'Response has been canceled.'; $this->close(); } diff --git a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php index efbaebc4e7..f0721aa8a2 100644 --- a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php @@ -105,6 +105,7 @@ class MockHttpClientTest extends HttpClientTestCase case 'testOnProgressError': case 'testReentrantBufferCallback': case 'testThrowingBufferCallback': + case 'testInfoOnCanceledResponse': $responses[] = new MockResponse($body, ['response_headers' => $headers]); break; diff --git a/src/Symfony/Contracts/HttpClient/ResponseInterface.php b/src/Symfony/Contracts/HttpClient/ResponseInterface.php index 8628c8daf1..b9917ac5f3 100644 --- a/src/Symfony/Contracts/HttpClient/ResponseInterface.php +++ b/src/Symfony/Contracts/HttpClient/ResponseInterface.php @@ -88,15 +88,16 @@ interface ResponseInterface * another, as the request/response progresses. * * The following info MUST be returned: - * - response_headers - an array modelled after the special $http_response_header variable - * - redirect_count - the number of redirects followed while executing the request - * - redirect_url - the resolved location of redirect responses, null otherwise - * - start_time - the time when the request was sent or 0.0 when it's pending - * - http_method - the HTTP verb of the last request - * - http_code - the last response code or 0 when it is not known yet - * - error - the error message when the transfer was aborted, null otherwise - * - user_data - the value of the "user_data" request option, null if not set - * - url - the last effective URL of the request + * - canceled (bool) - true if the response was canceled using ResponseInterface::cancel(), false otherwise + * - error (string|null) - the error message when the transfer was aborted, null otherwise + * - http_code (int) - the last response code or 0 when it is not known yet + * - http_method (string) - the HTTP verb of the last request + * - redirect_count (int) - the number of redirects followed while executing the request + * - redirect_url (string|null) - the resolved location of redirect responses, null otherwise + * - response_headers (array) - an array modelled after the special $http_response_header variable + * - start_time (float) - the time when the request was sent or 0.0 when it's pending + * - url (string) - the last effective URL of the request + * - user_data (mixed|null) - the value of the "user_data" request option, null if not set * * When the "capture_peer_cert_chain" option is true, the "peer_certificate_chain" * attribute SHOULD list the peer certificates as an array of OpenSSL X.509 resources. diff --git a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php index 0c76a41f64..11ba1ae6d2 100644 --- a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php +++ b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php @@ -515,6 +515,17 @@ abstract class HttpClientTestCase extends TestCase $response->getHeaders(); } + public function testInfoOnCanceledResponse() + { + $client = $this->getHttpClient(__FUNCTION__); + + $response = $client->request('GET', 'http://localhost:8057/timeout-header'); + + $this->assertFalse($response->getInfo('canceled')); + $response->cancel(); + $this->assertTrue($response->getInfo('canceled')); + } + public function testCancelInStream() { $client = $this->getHttpClient(__FUNCTION__);