From b7e032b3c0b63555d2a9756ab49d6ac7408c701c Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Tue, 6 Nov 2018 11:36:31 +0100 Subject: [PATCH 01/28] Use HTTPlug 2.0 (#114) * Adjust client signatures * Lock lower bounds for test dependencies * Use leanphp/phpspec-code-coverage as a maintained fork --- .travis.yml | 18 +++++++----------- composer.json | 12 ++++++++---- phpspec.ci.yml | 2 +- .../HttpClientPool/LeastUsedClientPoolSpec.php | 4 ---- src/BatchClient.php | 3 ++- src/HttpAsyncClientEmulator.php | 3 ++- src/HttpClientDecorator.php | 3 ++- src/HttpClientEmulator.php | 3 ++- src/HttpClientPool.php | 3 ++- src/HttpClientPoolItem.php | 3 ++- src/HttpClientRouter.php | 3 ++- src/HttpMethodsClient.php | 2 +- src/PluginClient.php | 3 ++- 13 files changed, 33 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6af5f34..0c9a55f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,6 @@ language: php - sudo: false -dist: trusty - cache: directories: - $HOME/.composer/cache/files @@ -19,17 +16,15 @@ branches: matrix: fast_finish: true include: - - php: 7.1 - env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" DEPENDENCIES="doctrine/instantiator:^1.1" + - php: 7.0 + env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" # Test the latest stable release - - php: 5.4 - - php: 5.5 - - php: 5.6 - php: 7.0 - php: 7.1 - php: 7.2 - env: COVERAGE=true TEST_COMMAND="composer test-ci" DEPENDENCIES="henrikbjorn/phpspec-code-coverage:^1.0" + - php: 7.2 + env: COVERAGE=true TEST_COMMAND="composer test-ci" DEPENDENCIES="leanphp/phpspec-code-coverage" # Test LTS versions - php: 7.1 @@ -44,9 +39,10 @@ matrix: env: STABILITY="dev" allow_failures: - # Latest dev is allowed to fail. + - php: 7.3 + sudo: required - env: STABILITY="dev" - + before_install: - if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi - if ! [ -z "$STABILITY" ]; then composer config minimum-stability ${STABILITY}; fi; diff --git a/composer.json b/composer.json index 4695c4c..fc3d1c1 100644 --- a/composer.json +++ b/composer.json @@ -11,15 +11,18 @@ } ], "require": { - "php": "^5.4 || ^7.0", - "php-http/httplug": "^1.1", + "php": "^7.0", + "php-http/httplug": "^2.0", "php-http/message-factory": "^1.0", "php-http/message": "^1.6", "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0" }, "require-dev": { - "phpspec/phpspec": "^2.5 || ^3.4 || ^4.2", - "guzzlehttp/psr7": "^1.4" + "doctrine/instantiator": ">=1.0.5", + "guzzlehttp/psr7": "^1.4", + "phpspec/phpspec": "^3.4 || ^4.2", + "phpspec/prophecy": ">=1.8", + "sebastian/comparator": ">=2" }, "suggest": { "php-http/logger-plugin": "PSR-3 Logger plugin", @@ -37,6 +40,7 @@ }, "extra": { "branch-alias": { + "dev-2.x": "2.x-dev", "dev-master": "1.8-dev" } } diff --git a/phpspec.ci.yml b/phpspec.ci.yml index 0838ef5..d8e1383 100644 --- a/phpspec.ci.yml +++ b/phpspec.ci.yml @@ -4,7 +4,7 @@ suites: psr4_prefix: Http\Client\Common formatter.name: pretty extensions: - - PhpSpec\Extension\CodeCoverageExtension + LeanPHP\PhpSpec\CodeCoverage\CodeCoverageExtension: ~ code_coverage: format: clover output: build/coverage.xml diff --git a/spec/HttpClientPool/LeastUsedClientPoolSpec.php b/spec/HttpClientPool/LeastUsedClientPoolSpec.php index a976c31..82855d9 100644 --- a/spec/HttpClientPool/LeastUsedClientPoolSpec.php +++ b/spec/HttpClientPool/LeastUsedClientPoolSpec.php @@ -72,10 +72,6 @@ public function it_reenable_client(HttpClient $client, RequestInterface $request public function it_uses_the_lowest_request_client(HttpClientPoolItem $client1, HttpClientPoolItem $client2, RequestInterface $request, ResponseInterface $response) { - if (extension_loaded('xdebug')) { - throw new SkippingException('This test fail when xdebug is enable on PHP < 7'); - } - $this->addHttpClient($client1); $this->addHttpClient($client2); diff --git a/src/BatchClient.php b/src/BatchClient.php index 2036355..2a39904 100644 --- a/src/BatchClient.php +++ b/src/BatchClient.php @@ -6,6 +6,7 @@ use Http\Client\HttpClient; use Http\Client\Common\Exception\BatchException; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; /** * BatchClient allow to sends multiple request and retrieve a Batch Result. @@ -32,7 +33,7 @@ public function __construct(HttpClient $client) /** * {@inheritdoc} */ - public function sendRequest(RequestInterface $request) + public function sendRequest(RequestInterface $request): ResponseInterface { return $this->client->sendRequest($request); } diff --git a/src/HttpAsyncClientEmulator.php b/src/HttpAsyncClientEmulator.php index c0ba354..ce16f84 100644 --- a/src/HttpAsyncClientEmulator.php +++ b/src/HttpAsyncClientEmulator.php @@ -5,6 +5,7 @@ use Http\Client\Exception; use Http\Client\Promise; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; /** * Emulates an HTTP Async Client in an HTTP Client. @@ -18,7 +19,7 @@ trait HttpAsyncClientEmulator * * @see HttpClient::sendRequest */ - abstract public function sendRequest(RequestInterface $request); + abstract public function sendRequest(RequestInterface $request): ResponseInterface; /** * {@inheritdoc} diff --git a/src/HttpClientDecorator.php b/src/HttpClientDecorator.php index a33d5ef..da5a1bb 100644 --- a/src/HttpClientDecorator.php +++ b/src/HttpClientDecorator.php @@ -4,6 +4,7 @@ use Http\Client\HttpClient; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; /** * Decorates an HTTP Client. @@ -22,7 +23,7 @@ trait HttpClientDecorator * * @see HttpClient::sendRequest */ - public function sendRequest(RequestInterface $request) + public function sendRequest(RequestInterface $request): ResponseInterface { return $this->httpClient->sendRequest($request); } diff --git a/src/HttpClientEmulator.php b/src/HttpClientEmulator.php index dbec1ab..8e6472a 100644 --- a/src/HttpClientEmulator.php +++ b/src/HttpClientEmulator.php @@ -3,6 +3,7 @@ namespace Http\Client\Common; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; /** * Emulates an HTTP Client in an HTTP Async Client. @@ -16,7 +17,7 @@ trait HttpClientEmulator * * @see HttpClient::sendRequest */ - public function sendRequest(RequestInterface $request) + public function sendRequest(RequestInterface $request): ResponseInterface { $promise = $this->sendAsyncRequest($request); diff --git a/src/HttpClientPool.php b/src/HttpClientPool.php index 7ac292c..6f4597f 100644 --- a/src/HttpClientPool.php +++ b/src/HttpClientPool.php @@ -6,6 +6,7 @@ use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; /** * A http client pool allows to send requests on a pool of different http client using a specific strategy (least used, @@ -52,7 +53,7 @@ public function sendAsyncRequest(RequestInterface $request) /** * {@inheritdoc} */ - public function sendRequest(RequestInterface $request) + public function sendRequest(RequestInterface $request): ResponseInterface { return $this->chooseHttpClient()->sendRequest($request); } diff --git a/src/HttpClientPoolItem.php b/src/HttpClientPoolItem.php index 09cd6dd..a46ee2f 100644 --- a/src/HttpClientPoolItem.php +++ b/src/HttpClientPoolItem.php @@ -6,6 +6,7 @@ use Http\Client\HttpClient; use Psr\Http\Message\RequestInterface; use Http\Client\Exception; +use Psr\Http\Message\ResponseInterface; /** * A HttpClientPoolItem represent a HttpClient inside a Pool. @@ -50,7 +51,7 @@ public function __construct($client, $reenableAfter = null) /** * {@inheritdoc} */ - public function sendRequest(RequestInterface $request) + public function sendRequest(RequestInterface $request): ResponseInterface { if ($this->isDisabled()) { throw new Exception\RequestException('Cannot send the request as this client has been disabled', $request); diff --git a/src/HttpClientRouter.php b/src/HttpClientRouter.php index 9f72133..fa32c56 100644 --- a/src/HttpClientRouter.php +++ b/src/HttpClientRouter.php @@ -7,6 +7,7 @@ use Http\Client\HttpClient; use Http\Message\RequestMatcher; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; /** * Route a request to a specific client in the stack based using a RequestMatcher. @@ -23,7 +24,7 @@ final class HttpClientRouter implements HttpClient, HttpAsyncClient /** * {@inheritdoc} */ - public function sendRequest(RequestInterface $request) + public function sendRequest(RequestInterface $request): ResponseInterface { $client = $this->chooseHttpClient($request); diff --git a/src/HttpMethodsClient.php b/src/HttpMethodsClient.php index 58804fc..0ec1e14 100644 --- a/src/HttpMethodsClient.php +++ b/src/HttpMethodsClient.php @@ -198,7 +198,7 @@ public function send($method, $uri, array $headers = [], $body = null) * * {@inheritdoc} */ - public function sendRequest(RequestInterface $request) + public function sendRequest(RequestInterface $request): ResponseInterface { return $this->httpClient->sendRequest($request); } diff --git a/src/PluginClient.php b/src/PluginClient.php index 93aea8f..7413152 100644 --- a/src/PluginClient.php +++ b/src/PluginClient.php @@ -9,6 +9,7 @@ use Http\Client\Promise\HttpFulfilledPromise; use Http\Client\Promise\HttpRejectedPromise; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; use Symfony\Component\OptionsResolver\OptionsResolver; /** @@ -67,7 +68,7 @@ public function __construct($client, array $plugins = [], array $options = []) /** * {@inheritdoc} */ - public function sendRequest(RequestInterface $request) + public function sendRequest(RequestInterface $request): ResponseInterface { // If we don't have an http client, use the async call if (!($this->client instanceof HttpClient)) { From 1adbf741d75c20262b5e6723b3601a57bbd6b164 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Mon, 19 Nov 2018 11:51:04 +0100 Subject: [PATCH 02/28] [2.0] Remove deprecations (#116) Remove deprecated plugin option 'debug_plugins' --- CHANGELOG.md | 5 +++++ src/PluginClient.php | 18 +----------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a32a18d..6c268e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 2.0 (unreleased) + +### Removed +- Deprecated option `debug_plugins` has been removed from `PluginClient` + ## 1.8.2 (unreleased) ### Changed diff --git a/src/PluginClient.php b/src/PluginClient.php index 7413152..70419e3 100644 --- a/src/PluginClient.php +++ b/src/PluginClient.php @@ -109,28 +109,12 @@ public function sendAsyncRequest(RequestInterface $request) */ private function configure(array $options = []) { - if (isset($options['debug_plugins'])) { - @trigger_error('The "debug_plugins" option is deprecated since 1.5 and will be removed in 2.0.', E_USER_DEPRECATED); - } - $resolver = new OptionsResolver(); $resolver->setDefaults([ 'max_restarts' => 10, - 'debug_plugins' => [], ]); - $resolver - ->setAllowedTypes('debug_plugins', 'array') - ->setAllowedValues('debug_plugins', function (array $plugins) { - foreach ($plugins as $plugin) { - // Make sure each object passed with the `debug_plugins` is an instance of Plugin. - if (!$plugin instanceof Plugin) { - return false; - } - } - - return true; - }); + $resolver->setAllowedTypes('max_restarts', 'int'); return $resolver->resolve($options); } From 859f4c573c74fb7718ad818d9fd9c7d9624e7ab8 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Tue, 20 Nov 2018 16:04:45 +0100 Subject: [PATCH 03/28] [2.0] Remove plugin chain debug (#119) Complete removal of debug_plugins --- spec/PluginClientSpec.php | 43 --------------------------------------- src/PluginClient.php | 12 +---------- 2 files changed, 1 insertion(+), 54 deletions(-) diff --git a/spec/PluginClientSpec.php b/spec/PluginClientSpec.php index addb2e8..88406ae 100644 --- a/spec/PluginClientSpec.php +++ b/spec/PluginClientSpec.php @@ -87,47 +87,4 @@ function it_throws_loop_exception(HttpClient $httpClient, RequestInterface $requ $this->shouldThrow('Http\Client\Common\Exception\LoopException')->duringSendRequest($request); } - - function it_injects_debug_plugins(HttpClient $httpClient, ResponseInterface $response, RequestInterface $request, Plugin $plugin0, Plugin $plugin1, Plugin $debugPlugin) - { - $plugin0 - ->handleRequest( - $request, - Argument::type('callable'), - Argument::type('callable') - ) - ->shouldBeCalledTimes(1) - ->will(function ($args) { - return $args[1]($args[0]); - }) - ; - $plugin1 - ->handleRequest( - $request, - Argument::type('callable'), - Argument::type('callable') - ) - ->shouldBeCalledTimes(1) - ->will(function ($args) { - return $args[1]($args[0]); - }) - ; - - $debugPlugin - ->handleRequest( - $request, - Argument::type('callable'), - Argument::type('callable') - ) - ->shouldBeCalledTimes(3) - ->will(function ($args) { - return $args[1]($args[0]); - }) - ; - - $httpClient->sendRequest($request)->willReturn($response); - - $this->beConstructedWith($httpClient, [$plugin0, $plugin1], ['debug_plugins'=>[$debugPlugin]]); - $this->sendRequest($request); - } } diff --git a/src/PluginClient.php b/src/PluginClient.php index 70419e3..c3a5641 100644 --- a/src/PluginClient.php +++ b/src/PluginClient.php @@ -46,7 +46,6 @@ final class PluginClient implements HttpClient, HttpAsyncClient * @param array $options { * * @var int $max_restarts - * @var Plugin[] $debug_plugins an array of plugins that are injected between each normal plugin * } * * @throws \RuntimeException if client is not an instance of HttpClient or HttpAsyncClient @@ -131,16 +130,7 @@ private function createPluginChain($pluginList, callable $clientCallable) { $firstCallable = $lastCallable = $clientCallable; - /* - * Inject debug plugins between each plugin. - */ - $pluginListWithDebug = $this->options['debug_plugins']; - foreach ($pluginList as $plugin) { - $pluginListWithDebug[] = $plugin; - $pluginListWithDebug = array_merge($pluginListWithDebug, $this->options['debug_plugins']); - } - - while ($plugin = array_pop($pluginListWithDebug)) { + while ($plugin = array_pop($pluginList)) { $lastCallable = function (RequestInterface $request) use ($plugin, $lastCallable, &$firstCallable) { return $plugin->handleRequest($request, $lastCallable, $firstCallable); }; From 94c98c68ad18e73c06d6050076c90d2a786be079 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Tue, 20 Nov 2018 16:37:01 +0100 Subject: [PATCH 04/28] Require PHP CS fixer and add basic configuration --- .gitignore | 1 + .php_cs | 25 ++++++++++++++++--------- composer.json | 5 ++++- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 16b4a20..560b927 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /phpspec.yml /phpunit.xml /vendor/ +/.php_cs.cache diff --git a/.php_cs b/.php_cs index 23ba165..7da3701 100644 --- a/.php_cs +++ b/.php_cs @@ -1,13 +1,20 @@ setRules([ + '@PSR2' => true, + '@Symfony' => true, + 'array_syntax' => [ + 'syntax' => 'short', + ], +]); -use SLLH\StyleCIBridge\ConfigBridge; +$finder = PhpCsFixer\Finder::create(); +$finder->in([ + 'src', + 'spec' +]); -return ConfigBridge::create(); +$config->setFinder($finder); + +return $config; diff --git a/composer.json b/composer.json index fc3d1c1..882758b 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "guzzlehttp/psr7": "^1.4", "phpspec/phpspec": "^3.4 || ^4.2", "phpspec/prophecy": ">=1.8", - "sebastian/comparator": ">=2" + "sebastian/comparator": ">=2", + "friendsofphp/php-cs-fixer": "^2.2" }, "suggest": { "php-http/logger-plugin": "PSR-3 Logger plugin", @@ -35,6 +36,8 @@ } }, "scripts": { + "cs-check": "vendor/bin/php-cs-fixer fix --dry-run", + "cs-fix": "vendor/bin/php-cs-fixer fix", "test": "vendor/bin/phpspec run", "test-ci": "vendor/bin/phpspec run -c phpspec.ci.yml" }, From 9f6d02cff27d988cfac948a88a041621d6945581 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Tue, 20 Nov 2018 16:39:58 +0100 Subject: [PATCH 05/28] Apply the base configuration --- spec/BatchClientSpec.php | 6 +- spec/BatchResultSpec.php | 10 +-- spec/EmulatedHttpAsyncClientSpec.php | 14 ++-- spec/EmulatedHttpClientSpec.php | 15 ++-- spec/Exception/BatchExceptionSpec.php | 11 ++- spec/FlexibleHttpClientSpec.php | 16 ++-- .../LeastUsedClientPoolSpec.php | 1 - spec/HttpClientPoolItemSpec.php | 12 +-- spec/HttpClientRouterSpec.php | 14 ++-- spec/HttpMethodsClientSpec.php | 27 ++++--- spec/Plugin/AddHostPluginSpec.php | 14 ++-- spec/Plugin/AddPathPluginSpec.php | 14 ++-- spec/Plugin/AuthenticationPluginSpec.php | 10 +-- spec/Plugin/BaseUriPluginSpec.php | 14 ++-- spec/Plugin/ContentLengthPluginSpec.php | 10 +-- spec/Plugin/ContentTypePluginSpec.php | 30 ++++---- spec/Plugin/CookiePluginSpec.php | 32 ++++---- spec/Plugin/DecoderPluginSpec.php | 22 +++--- spec/Plugin/ErrorPluginSpec.php | 20 ++--- spec/Plugin/HeaderAppendPluginSpec.php | 7 +- spec/Plugin/HeaderDefaultsPluginSpec.php | 5 +- spec/Plugin/HeaderRemovePluginSpec.php | 5 +- spec/Plugin/HeaderSetPluginSpec.php | 7 +- spec/Plugin/HistoryPluginSpec.php | 14 ++-- spec/Plugin/QueryDefaultsPluginSpec.php | 1 - spec/Plugin/RedirectPluginSpec.php | 74 +++++++++---------- spec/Plugin/RequestMatcherPluginSpec.php | 12 +-- spec/Plugin/RetryPluginSpec.php | 40 +++++----- spec/PluginClientFactorySpec.php | 6 +- spec/PluginClientSpec.php | 19 +++-- src/HttpClientRouter.php | 2 +- src/Plugin.php | 2 +- src/Plugin/BaseUriPlugin.php | 2 +- src/Plugin/ContentTypePlugin.php | 6 +- src/Plugin/ErrorPlugin.php | 2 +- src/Plugin/RetryPlugin.php | 4 +- 36 files changed, 235 insertions(+), 265 deletions(-) diff --git a/spec/BatchClientSpec.php b/spec/BatchClientSpec.php index 962f00a..8b7e96d 100644 --- a/spec/BatchClientSpec.php +++ b/spec/BatchClientSpec.php @@ -9,12 +9,12 @@ class BatchClientSpec extends ObjectBehavior { - function let(HttpClient $client) + public function let(HttpClient $client) { $this->beAnInstanceOf('Http\Client\Common\BatchClient', [$client]); } - function it_send_multiple_request_using_send_request(HttpClient $client, RequestInterface $request1, RequestInterface $request2, ResponseInterface $response1, ResponseInterface $response2) + public function it_send_multiple_request_using_send_request(HttpClient $client, RequestInterface $request1, RequestInterface $request2, ResponseInterface $response1, ResponseInterface $response2) { $client->sendRequest($request1)->willReturn($response1); $client->sendRequest($request2)->willReturn($response2); @@ -22,7 +22,7 @@ function it_send_multiple_request_using_send_request(HttpClient $client, Request $this->sendRequests([$request1, $request2])->shouldReturnAnInstanceOf('Http\Client\Common\BatchResult'); } - function it_throw_batch_exception_if_one_or_more_request_failed(HttpClient $client, RequestInterface $request1, RequestInterface $request2, ResponseInterface $response) + public function it_throw_batch_exception_if_one_or_more_request_failed(HttpClient $client, RequestInterface $request1, RequestInterface $request2, ResponseInterface $response) { $client->sendRequest($request1)->willReturn($response); $client->sendRequest($request2)->willThrow('Http\Client\Exception\HttpException'); diff --git a/spec/BatchResultSpec.php b/spec/BatchResultSpec.php index c4618ac..aa3bb14 100644 --- a/spec/BatchResultSpec.php +++ b/spec/BatchResultSpec.php @@ -9,12 +9,12 @@ class BatchResultSpec extends ObjectBehavior { - function it_is_initializable() + public function it_is_initializable() { $this->beAnInstanceOf('Http\Client\Common\BatchResult'); } - function it_is_immutable(RequestInterface $request, ResponseInterface $response) + public function it_is_immutable(RequestInterface $request, ResponseInterface $response) { $new = $this->addResponse($request, $response); @@ -23,7 +23,7 @@ function it_is_immutable(RequestInterface $request, ResponseInterface $response) $new->getResponses()->shouldReturn([$response]); } - function it_has_a_responses(RequestInterface $request, ResponseInterface $response) + public function it_has_a_responses(RequestInterface $request, ResponseInterface $response) { $new = $this->addResponse($request, $response); @@ -33,7 +33,7 @@ function it_has_a_responses(RequestInterface $request, ResponseInterface $respon $new->getResponses()->shouldReturn([$response]); } - function it_has_a_response_for_a_request(RequestInterface $request, ResponseInterface $response) + public function it_has_a_response_for_a_request(RequestInterface $request, ResponseInterface $response) { $new = $this->addResponse($request, $response); @@ -43,7 +43,7 @@ function it_has_a_response_for_a_request(RequestInterface $request, ResponseInte $new->isSuccessful($request)->shouldReturn(true); } - function it_keeps_exception_after_add_request(RequestInterface $request1, Exception $exception, RequestInterface $request2, ResponseInterface $response) + public function it_keeps_exception_after_add_request(RequestInterface $request1, Exception $exception, RequestInterface $request2, ResponseInterface $response) { $new = $this->addException($request1, $exception); $new = $new->addResponse($request2, $response); diff --git a/spec/EmulatedHttpAsyncClientSpec.php b/spec/EmulatedHttpAsyncClientSpec.php index b7a9edd..ca8a4d1 100644 --- a/spec/EmulatedHttpAsyncClientSpec.php +++ b/spec/EmulatedHttpAsyncClientSpec.php @@ -9,27 +9,27 @@ class EmulatedHttpAsyncClientSpec extends ObjectBehavior { - function let(HttpClient $httpClient) + public function let(HttpClient $httpClient) { $this->beConstructedWith($httpClient); } - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\EmulatedHttpAsyncClient'); } - function it_is_an_http_client() + public function it_is_an_http_client() { $this->shouldImplement('Http\Client\HttpClient'); } - function it_is_an_async_http_client() + public function it_is_an_async_http_client() { $this->shouldImplement('Http\Client\HttpAsyncClient'); } - function it_emulates_a_successful_request( + public function it_emulates_a_successful_request( HttpClient $httpClient, RequestInterface $request, ResponseInterface $response @@ -39,14 +39,14 @@ function it_emulates_a_successful_request( $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); } - function it_emulates_a_failed_request(HttpClient $httpClient, RequestInterface $request) + public function it_emulates_a_failed_request(HttpClient $httpClient, RequestInterface $request) { $httpClient->sendRequest($request)->willThrow('Http\Client\Exception\TransferException'); $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); } - function it_decorates_the_underlying_client( + public function it_decorates_the_underlying_client( HttpClient $httpClient, RequestInterface $request, ResponseInterface $response diff --git a/spec/EmulatedHttpClientSpec.php b/spec/EmulatedHttpClientSpec.php index 976f772..cf6e076 100644 --- a/spec/EmulatedHttpClientSpec.php +++ b/spec/EmulatedHttpClientSpec.php @@ -3,7 +3,6 @@ namespace spec\Http\Client\Common; use Http\Client\Exception\TransferException; -use Http\Client\HttpClient; use Http\Client\HttpAsyncClient; use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; @@ -12,27 +11,27 @@ class EmulatedHttpClientSpec extends ObjectBehavior { - function let(HttpAsyncClient $httpAsyncClient) + public function let(HttpAsyncClient $httpAsyncClient) { $this->beConstructedWith($httpAsyncClient); } - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\EmulatedHttpClient'); } - function it_is_an_http_client() + public function it_is_an_http_client() { $this->shouldImplement('Http\Client\HttpClient'); } - function it_is_an_async_http_client() + public function it_is_an_async_http_client() { $this->shouldImplement('Http\Client\HttpAsyncClient'); } - function it_emulates_a_successful_request( + public function it_emulates_a_successful_request( HttpAsyncClient $httpAsyncClient, RequestInterface $request, Promise $promise, @@ -47,7 +46,7 @@ function it_emulates_a_successful_request( $this->sendRequest($request)->shouldReturn($response); } - function it_emulates_a_failed_request(HttpAsyncClient $httpAsyncClient, RequestInterface $request, Promise $promise) + public function it_emulates_a_failed_request(HttpAsyncClient $httpAsyncClient, RequestInterface $request, Promise $promise) { $promise->wait()->shouldBeCalled(); $promise->getState()->willReturn(Promise::REJECTED); @@ -58,7 +57,7 @@ function it_emulates_a_failed_request(HttpAsyncClient $httpAsyncClient, RequestI $this->shouldThrow('Http\Client\Exception')->duringSendRequest($request); } - function it_decorates_the_underlying_client( + public function it_decorates_the_underlying_client( HttpAsyncClient $httpAsyncClient, RequestInterface $request, Promise $promise diff --git a/spec/Exception/BatchExceptionSpec.php b/spec/Exception/BatchExceptionSpec.php index fa8d8d6..0a32607 100644 --- a/spec/Exception/BatchExceptionSpec.php +++ b/spec/Exception/BatchExceptionSpec.php @@ -3,33 +3,32 @@ namespace spec\Http\Client\Common\Exception; use Http\Client\Common\BatchResult; -use Http\Client\Exception; use PhpSpec\ObjectBehavior; class BatchExceptionSpec extends ObjectBehavior { - function let() + public function let() { $batchResult = new BatchResult(); $this->beConstructedWith($batchResult); } - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\Exception\BatchException'); } - function it_is_a_runtime_exception() + public function it_is_a_runtime_exception() { $this->shouldHaveType('RuntimeException'); } - function it_is_an_exception() + public function it_is_an_exception() { $this->shouldImplement('Http\Client\Exception'); } - function it_has_a_batch_result() + public function it_has_a_batch_result() { $this->getResult()->shouldHaveType('Http\Client\Common\BatchResult'); } diff --git a/spec/FlexibleHttpClientSpec.php b/spec/FlexibleHttpClientSpec.php index 70e6e4d..769b4c3 100644 --- a/spec/FlexibleHttpClientSpec.php +++ b/spec/FlexibleHttpClientSpec.php @@ -11,34 +11,34 @@ class FlexibleHttpClientSpec extends ObjectBehavior { - function let(HttpClient $httpClient) + public function let(HttpClient $httpClient) { $this->beConstructedWith($httpClient); } - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\FlexibleHttpClient'); } - function it_is_an_http_client() + public function it_is_an_http_client() { $this->shouldImplement('Http\Client\HttpClient'); } - function it_is_an_async_http_client() + public function it_is_an_async_http_client() { $this->shouldImplement('Http\Client\HttpAsyncClient'); } - function it_throw_exception_if_invalid_client() + public function it_throw_exception_if_invalid_client() { $this->beConstructedWith(null); $this->shouldThrow('\LogicException')->duringInstantiation(); } - function it_emulates_an_async_client( + public function it_emulates_an_async_client( HttpClient $httpClient, RequestInterface $syncRequest, ResponseInterface $syncResponse, @@ -57,7 +57,7 @@ function it_emulates_an_async_client( $promise->wait()->shouldReturn($asyncResponse); } - function it_emulates_a_client( + public function it_emulates_a_client( HttpAsyncClient $httpAsyncClient, RequestInterface $asyncRequest, Promise $promise, @@ -75,7 +75,7 @@ function it_emulates_a_client( $this->sendRequest($syncRequest)->shouldReturn($syncResponse); } - function it_does_not_emulate_a_client($client, RequestInterface $syncRequest, RequestInterface $asyncRequest) + public function it_does_not_emulate_a_client($client, RequestInterface $syncRequest, RequestInterface $asyncRequest) { $client->implement('Http\Client\HttpClient'); $client->implement('Http\Client\HttpAsyncClient'); diff --git a/spec/HttpClientPool/LeastUsedClientPoolSpec.php b/spec/HttpClientPool/LeastUsedClientPoolSpec.php index 82855d9..8642c31 100644 --- a/spec/HttpClientPool/LeastUsedClientPoolSpec.php +++ b/spec/HttpClientPool/LeastUsedClientPoolSpec.php @@ -6,7 +6,6 @@ use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; use Http\Promise\Promise; -use PhpSpec\Exception\Example\SkippingException; use PhpSpec\ObjectBehavior; use Prophecy\Argument; use Psr\Http\Message\RequestInterface; diff --git a/spec/HttpClientPoolItemSpec.php b/spec/HttpClientPoolItemSpec.php index 059ec8d..cba68d8 100644 --- a/spec/HttpClientPoolItemSpec.php +++ b/spec/HttpClientPoolItemSpec.php @@ -156,7 +156,7 @@ public function getState() public function wait($unwrap = true) { - if ($this->state === Promise::FULFILLED) { + if (Promise::FULFILLED === $this->state) { if (!$unwrap) { return; } @@ -164,7 +164,7 @@ public function wait($unwrap = true) return $this->response; } - if ($this->state === Promise::REJECTED) { + if (Promise::REJECTED === $this->state) { if (!$unwrap) { return; } @@ -175,7 +175,7 @@ public function wait($unwrap = true) while (count($this->queue) > 0) { $callbacks = array_shift($this->queue); - if ($this->response !== null) { + if (null !== $this->response) { try { $this->response = $callbacks[0]($this->response); $this->exception = null; @@ -183,7 +183,7 @@ public function wait($unwrap = true) $this->response = null; $this->exception = $exception; } - } elseif ($this->exception !== null) { + } elseif (null !== $this->exception) { try { $this->response = $callbacks[1]($this->exception); $this->exception = null; @@ -194,7 +194,7 @@ public function wait($unwrap = true) } } - if ($this->response !== null) { + if (null !== $this->response) { $this->state = Promise::FULFILLED; if ($unwrap) { @@ -202,7 +202,7 @@ public function wait($unwrap = true) } } - if ($this->exception !== null) { + if (null !== $this->exception) { $this->state = Promise::REJECTED; if ($unwrap) { diff --git a/spec/HttpClientRouterSpec.php b/spec/HttpClientRouterSpec.php index 1119722..e43acea 100644 --- a/spec/HttpClientRouterSpec.php +++ b/spec/HttpClientRouterSpec.php @@ -12,22 +12,22 @@ class HttpClientRouterSpec extends ObjectBehavior { - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\HttpClientRouter'); } - function it_is_an_http_client() + public function it_is_an_http_client() { $this->shouldImplement('Http\Client\HttpClient'); } - function it_is_an_async_http_client() + public function it_is_an_async_http_client() { $this->shouldImplement('Http\Client\HttpAsyncClient'); } - function it_send_request(RequestMatcher $matcher, HttpClient $client, RequestInterface $request, ResponseInterface $response) + public function it_send_request(RequestMatcher $matcher, HttpClient $client, RequestInterface $request, ResponseInterface $response) { $this->addClient($client, $matcher); $matcher->matches($request)->willReturn(true); @@ -36,7 +36,7 @@ function it_send_request(RequestMatcher $matcher, HttpClient $client, RequestInt $this->sendRequest($request)->shouldReturn($response); } - function it_send_async_request(RequestMatcher $matcher, HttpAsyncClient $client, RequestInterface $request, Promise $promise) + public function it_send_async_request(RequestMatcher $matcher, HttpAsyncClient $client, RequestInterface $request, Promise $promise) { $this->addClient($client, $matcher); $matcher->matches($request)->willReturn(true); @@ -45,7 +45,7 @@ function it_send_async_request(RequestMatcher $matcher, HttpAsyncClient $client, $this->sendAsyncRequest($request)->shouldReturn($promise); } - function it_throw_exception_on_send_request(RequestMatcher $matcher, HttpClient $client, RequestInterface $request) + public function it_throw_exception_on_send_request(RequestMatcher $matcher, HttpClient $client, RequestInterface $request) { $this->addClient($client, $matcher); $matcher->matches($request)->willReturn(false); @@ -53,7 +53,7 @@ function it_throw_exception_on_send_request(RequestMatcher $matcher, HttpClient $this->shouldThrow('Http\Client\Exception\RequestException')->duringSendRequest($request); } - function it_throw_exception_on_send_async_request(RequestMatcher $matcher, HttpAsyncClient $client, RequestInterface $request) + public function it_throw_exception_on_send_async_request(RequestMatcher $matcher, HttpAsyncClient $client, RequestInterface $request) { $this->addClient($client, $matcher); $matcher->matches($request)->willReturn(false); diff --git a/spec/HttpMethodsClientSpec.php b/spec/HttpMethodsClientSpec.php index 07c0b47..b68c8c4 100644 --- a/spec/HttpMethodsClientSpec.php +++ b/spec/HttpMethodsClientSpec.php @@ -2,7 +2,6 @@ namespace spec\Http\Client\Common; -use Http\Client\BatchResult; use Http\Client\HttpClient; use Http\Client\Common\HttpMethodsClient; use Http\Message\MessageFactory; @@ -12,73 +11,73 @@ class HttpMethodsClientSpec extends ObjectBehavior { - function let(HttpClient $client, MessageFactory $messageFactory) + public function let(HttpClient $client, MessageFactory $messageFactory) { $this->beAnInstanceOf( 'spec\Http\Client\Common\HttpMethodsClientStub', [ $client, - $messageFactory + $messageFactory, ] ); } - function it_sends_a_get_request() + public function it_sends_a_get_request() { $data = HttpMethodsClientStub::$requestData; $this->get($data['uri'], $data['headers'])->shouldReturn(true); } - function it_sends_a_head_request() + public function it_sends_a_head_request() { $data = HttpMethodsClientStub::$requestData; $this->head($data['uri'], $data['headers'])->shouldReturn(true); } - function it_sends_a_trace_request() + public function it_sends_a_trace_request() { $data = HttpMethodsClientStub::$requestData; $this->trace($data['uri'], $data['headers'])->shouldReturn(true); } - function it_sends_a_post_request() + public function it_sends_a_post_request() { $data = HttpMethodsClientStub::$requestData; $this->post($data['uri'], $data['headers'], $data['body'])->shouldReturn(true); } - function it_sends_a_put_request() + public function it_sends_a_put_request() { $data = HttpMethodsClientStub::$requestData; $this->put($data['uri'], $data['headers'], $data['body'])->shouldReturn(true); } - function it_sends_a_patch_request() + public function it_sends_a_patch_request() { $data = HttpMethodsClientStub::$requestData; $this->patch($data['uri'], $data['headers'], $data['body'])->shouldReturn(true); } - function it_sends_a_delete_request() + public function it_sends_a_delete_request() { $data = HttpMethodsClientStub::$requestData; $this->delete($data['uri'], $data['headers'], $data['body'])->shouldReturn(true); } - function it_sends_a_options_request() + public function it_sends_a_options_request() { $data = HttpMethodsClientStub::$requestData; $this->options($data['uri'], $data['headers'], $data['body'])->shouldReturn(true); } - function it_sends_request_with_underlying_client(HttpClient $client, MessageFactory $messageFactory, RequestInterface $request, ResponseInterface $response) + public function it_sends_request_with_underlying_client(HttpClient $client, MessageFactory $messageFactory, RequestInterface $request, ResponseInterface $response) { $client->sendRequest($request)->shouldBeCalled()->willReturn($response); @@ -90,11 +89,11 @@ function it_sends_request_with_underlying_client(HttpClient $client, MessageFact class HttpMethodsClientStub extends HttpMethodsClient { public static $requestData = [ - 'uri' => '/uri', + 'uri' => '/uri', 'headers' => [ 'Content-Type' => 'text/plain', ], - 'body' => 'body' + 'body' => 'body', ]; /** diff --git a/spec/Plugin/AddHostPluginSpec.php b/spec/Plugin/AddHostPluginSpec.php index caf4f21..a6630bd 100644 --- a/spec/Plugin/AddHostPluginSpec.php +++ b/spec/Plugin/AddHostPluginSpec.php @@ -2,34 +2,32 @@ namespace spec\Http\Client\Common\Plugin; -use Http\Message\StreamFactory; -use Http\Message\UriFactory; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; use PhpSpec\ObjectBehavior; class AddHostPluginSpec extends ObjectBehavior { - function let(UriInterface $uri) + public function let(UriInterface $uri) { $this->beConstructedWith($uri); } - function it_is_initializable(UriInterface $uri) + public function it_is_initializable(UriInterface $uri) { $uri->getHost()->shouldBeCalled()->willReturn('example.com'); $this->shouldHaveType('Http\Client\Common\Plugin\AddHostPlugin'); } - function it_is_a_plugin(UriInterface $uri) + public function it_is_a_plugin(UriInterface $uri) { $uri->getHost()->shouldBeCalled()->willReturn('example.com'); $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_adds_domain( + public function it_adds_domain( RequestInterface $request, UriInterface $host, UriInterface $uri @@ -50,7 +48,7 @@ function it_adds_domain( $this->handleRequest($request, function () {}, function () {}); } - function it_replaces_domain( + public function it_replaces_domain( RequestInterface $request, UriInterface $host, UriInterface $uri @@ -70,7 +68,7 @@ function it_replaces_domain( $this->handleRequest($request, function () {}, function () {}); } - function it_does_nothing_when_domain_exists( + public function it_does_nothing_when_domain_exists( RequestInterface $request, UriInterface $host, UriInterface $uri diff --git a/spec/Plugin/AddPathPluginSpec.php b/spec/Plugin/AddPathPluginSpec.php index a7ec9b5..c95301c 100644 --- a/spec/Plugin/AddPathPluginSpec.php +++ b/spec/Plugin/AddPathPluginSpec.php @@ -2,34 +2,32 @@ namespace spec\Http\Client\Common\Plugin; -use Http\Message\StreamFactory; -use Http\Message\UriFactory; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; use PhpSpec\ObjectBehavior; class AddPathPluginSpec extends ObjectBehavior { - function let(UriInterface $uri) + public function let(UriInterface $uri) { $this->beConstructedWith($uri); } - function it_is_initializable(UriInterface $uri) + public function it_is_initializable(UriInterface $uri) { $uri->getPath()->shouldBeCalled()->willReturn('/api'); $this->shouldHaveType('Http\Client\Common\Plugin\AddPathPlugin'); } - function it_is_a_plugin(UriInterface $uri) + public function it_is_a_plugin(UriInterface $uri) { $uri->getPath()->shouldBeCalled()->willReturn('/api'); $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_adds_path( + public function it_adds_path( RequestInterface $request, UriInterface $host, UriInterface $uri @@ -46,7 +44,7 @@ function it_adds_path( $this->handleRequest($request, function () {}, function () {}); } - function it_throws_exception_on_trailing_slash(UriInterface $host) + public function it_throws_exception_on_trailing_slash(UriInterface $host) { $host->getPath()->shouldBeCalled()->willReturn('/api/'); @@ -54,7 +52,7 @@ function it_throws_exception_on_trailing_slash(UriInterface $host) $this->shouldThrow('\LogicException')->duringInstantiation(); } - function it_throws_exception_on_empty_path(UriInterface $host) + public function it_throws_exception_on_empty_path(UriInterface $host) { $host->getPath()->shouldBeCalled()->willReturn(''); diff --git a/spec/Plugin/AuthenticationPluginSpec.php b/spec/Plugin/AuthenticationPluginSpec.php index 02d1187..549b507 100644 --- a/spec/Plugin/AuthenticationPluginSpec.php +++ b/spec/Plugin/AuthenticationPluginSpec.php @@ -10,26 +10,26 @@ class AuthenticationPluginSpec extends ObjectBehavior { - function let(Authentication $authentication) + public function let(Authentication $authentication) { $this->beConstructedWith($authentication); } - function it_is_initializable(Authentication $authentication) + public function it_is_initializable(Authentication $authentication) { $this->shouldHaveType('Http\Client\Common\Plugin\AuthenticationPlugin'); } - function it_is_a_plugin() + public function it_is_a_plugin() { $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_sends_an_authenticated_request(Authentication $authentication, RequestInterface $notAuthedRequest, RequestInterface $authedRequest, Promise $promise) + public function it_sends_an_authenticated_request(Authentication $authentication, RequestInterface $notAuthedRequest, RequestInterface $authedRequest, Promise $promise) { $authentication->authenticate($notAuthedRequest)->willReturn($authedRequest); - $next = function (RequestInterface $request) use($authedRequest, $promise) { + $next = function (RequestInterface $request) use ($authedRequest, $promise) { if (Argument::is($authedRequest->getWrappedObject())->scoreArgument($request)) { return $promise->getWrappedObject(); } diff --git a/spec/Plugin/BaseUriPluginSpec.php b/spec/Plugin/BaseUriPluginSpec.php index 2faf769..e2f8c46 100644 --- a/spec/Plugin/BaseUriPluginSpec.php +++ b/spec/Plugin/BaseUriPluginSpec.php @@ -2,20 +2,18 @@ namespace spec\Http\Client\Common\Plugin; -use Http\Message\StreamFactory; -use Http\Message\UriFactory; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; use PhpSpec\ObjectBehavior; class BaseUriPluginSpec extends ObjectBehavior { - function let(UriInterface $uri) + public function let(UriInterface $uri) { $this->beConstructedWith($uri); } - function it_is_initializable(UriInterface $uri) + public function it_is_initializable(UriInterface $uri) { $uri->getHost()->shouldBeCalled()->willReturn('example.com'); $uri->getPath()->shouldBeCalled()->willReturn('/api'); @@ -23,7 +21,7 @@ function it_is_initializable(UriInterface $uri) $this->shouldHaveType('Http\Client\Common\Plugin\BaseUriPlugin'); } - function it_is_a_plugin(UriInterface $uri) + public function it_is_a_plugin(UriInterface $uri) { $uri->getHost()->shouldBeCalled()->willReturn('example.com'); $uri->getPath()->shouldBeCalled()->willReturn('/api'); @@ -31,7 +29,7 @@ function it_is_a_plugin(UriInterface $uri) $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_adds_domain_and_path( + public function it_adds_domain_and_path( RequestInterface $request, UriInterface $host, UriInterface $uri @@ -55,7 +53,7 @@ function it_adds_domain_and_path( $this->handleRequest($request, function () {}, function () {}); } - function it_adds_domain( + public function it_adds_domain( RequestInterface $request, UriInterface $host, UriInterface $uri @@ -77,7 +75,7 @@ function it_adds_domain( $this->handleRequest($request, function () {}, function () {}); } - function it_replaces_domain_and_adds_path( + public function it_replaces_domain_and_adds_path( RequestInterface $request, UriInterface $host, UriInterface $uri diff --git a/spec/Plugin/ContentLengthPluginSpec.php b/spec/Plugin/ContentLengthPluginSpec.php index 4ec2ba7..6624f6c 100644 --- a/spec/Plugin/ContentLengthPluginSpec.php +++ b/spec/Plugin/ContentLengthPluginSpec.php @@ -10,17 +10,17 @@ class ContentLengthPluginSpec extends ObjectBehavior { - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\Plugin\ContentLengthPlugin'); } - function it_is_a_plugin() + public function it_is_a_plugin() { $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_adds_content_length_header(RequestInterface $request, StreamInterface $stream) + public function it_adds_content_length_header(RequestInterface $request, StreamInterface $stream) { $request->hasHeader('Content-Length')->shouldBeCalled()->willReturn(false); $request->getBody()->shouldBeCalled()->willReturn($stream); @@ -30,9 +30,9 @@ function it_adds_content_length_header(RequestInterface $request, StreamInterfac $this->handleRequest($request, function () {}, function () {}); } - function it_streams_chunked_if_no_size(RequestInterface $request, StreamInterface $stream) + public function it_streams_chunked_if_no_size(RequestInterface $request, StreamInterface $stream) { - if(defined('HHVM_VERSION')) { + if (defined('HHVM_VERSION')) { throw new SkippingException('Skipping test on hhvm, as there is no chunk encoding on hhvm'); } diff --git a/spec/Plugin/ContentTypePluginSpec.php b/spec/Plugin/ContentTypePluginSpec.php index 3df7d87..d2a6ffa 100644 --- a/spec/Plugin/ContentTypePluginSpec.php +++ b/spec/Plugin/ContentTypePluginSpec.php @@ -2,25 +2,22 @@ namespace spec\Http\Client\Common\Plugin; -use PhpSpec\Exception\Example\SkippingException; use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\StreamInterface; use PhpSpec\ObjectBehavior; -use Prophecy\Argument; class ContentTypePluginSpec extends ObjectBehavior { - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\Plugin\ContentTypePlugin'); } - function it_is_a_plugin() + public function it_is_a_plugin() { $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_adds_json_content_type_header(RequestInterface $request) + public function it_adds_json_content_type_header(RequestInterface $request) { $request->hasHeader('Content-Type')->shouldBeCalled()->willReturn(false); $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for(json_encode(['foo' => 'bar']))); @@ -29,7 +26,7 @@ function it_adds_json_content_type_header(RequestInterface $request) $this->handleRequest($request, function () {}, function () {}); } - function it_adds_xml_content_type_header(RequestInterface $request) + public function it_adds_xml_content_type_header(RequestInterface $request) { $request->hasHeader('Content-Type')->shouldBeCalled()->willReturn(false); $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for('bar')); @@ -38,7 +35,7 @@ function it_adds_xml_content_type_header(RequestInterface $request) $this->handleRequest($request, function () {}, function () {}); } - function it_does_not_set_content_type_header(RequestInterface $request) + public function it_does_not_set_content_type_header(RequestInterface $request) { $request->hasHeader('Content-Type')->shouldBeCalled()->willReturn(false); $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for('foo')); @@ -47,7 +44,7 @@ function it_does_not_set_content_type_header(RequestInterface $request) $this->handleRequest($request, function () {}, function () {}); } - function it_does_not_set_content_type_header_if_already_one(RequestInterface $request) + public function it_does_not_set_content_type_header_if_already_one(RequestInterface $request) { $request->hasHeader('Content-Type')->shouldBeCalled()->willReturn(true); $request->getBody()->shouldNotBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for('foo')); @@ -56,7 +53,7 @@ function it_does_not_set_content_type_header_if_already_one(RequestInterface $re $this->handleRequest($request, function () {}, function () {}); } - function it_does_not_set_content_type_header_if_size_0_or_unknown(RequestInterface $request) + public function it_does_not_set_content_type_header_if_size_0_or_unknown(RequestInterface $request) { $request->hasHeader('Content-Type')->shouldBeCalled()->willReturn(false); $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for()); @@ -65,10 +62,10 @@ function it_does_not_set_content_type_header_if_size_0_or_unknown(RequestInterfa $this->handleRequest($request, function () {}, function () {}); } - function it_adds_xml_content_type_header_if_size_limit_is_not_reached_using_default_value(RequestInterface $request) + public function it_adds_xml_content_type_header_if_size_limit_is_not_reached_using_default_value(RequestInterface $request) { $this->beConstructedWith([ - 'skip_detection' => true + 'skip_detection' => true, ]); $request->hasHeader('Content-Type')->shouldBeCalled()->willReturn(false); @@ -78,11 +75,11 @@ function it_adds_xml_content_type_header_if_size_limit_is_not_reached_using_defa $this->handleRequest($request, function () {}, function () {}); } - function it_adds_xml_content_type_header_if_size_limit_is_not_reached(RequestInterface $request) + public function it_adds_xml_content_type_header_if_size_limit_is_not_reached(RequestInterface $request) { $this->beConstructedWith([ 'skip_detection' => true, - 'size_limit' => 32000000 + 'size_limit' => 32000000, ]); $request->hasHeader('Content-Type')->shouldBeCalled()->willReturn(false); @@ -92,11 +89,11 @@ function it_adds_xml_content_type_header_if_size_limit_is_not_reached(RequestInt $this->handleRequest($request, function () {}, function () {}); } - function it_does_not_set_content_type_header_if_size_limit_is_reached(RequestInterface $request) + public function it_does_not_set_content_type_header_if_size_limit_is_reached(RequestInterface $request) { $this->beConstructedWith([ 'skip_detection' => true, - 'size_limit' => 8 + 'size_limit' => 8, ]); $request->hasHeader('Content-Type')->shouldBeCalled()->willReturn(false); @@ -105,5 +102,4 @@ function it_does_not_set_content_type_header_if_size_limit_is_reached(RequestInt $this->handleRequest($request, function () {}, function () {}); } - } diff --git a/spec/Plugin/CookiePluginSpec.php b/spec/Plugin/CookiePluginSpec.php index 2bb47e7..1f021b1 100644 --- a/spec/Plugin/CookiePluginSpec.php +++ b/spec/Plugin/CookiePluginSpec.php @@ -16,24 +16,24 @@ class CookiePluginSpec extends ObjectBehavior { private $cookieJar; - function let() + public function let() { $this->cookieJar = new CookieJar(); $this->beConstructedWith($this->cookieJar); } - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\Plugin\CookiePlugin'); } - function it_is_a_plugin() + public function it_is_a_plugin() { $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_loads_cookie(RequestInterface $request, UriInterface $uri, Promise $promise) + public function it_loads_cookie(RequestInterface $request, UriInterface $uri, Promise $promise) { $cookie = new Cookie('name', 'value', 86400, 'test.com'); $this->cookieJar->addCookie($cookie); @@ -51,7 +51,7 @@ function it_loads_cookie(RequestInterface $request, UriInterface $uri, Promise $ }, function () {}); } - function it_combines_multiple_cookies_into_one_header(RequestInterface $request, UriInterface $uri, Promise $promise) + public function it_combines_multiple_cookies_into_one_header(RequestInterface $request, UriInterface $uri, Promise $promise) { $cookie = new Cookie('name', 'value', 86400, 'test.com'); $cookie2 = new Cookie('name2', 'value2', 86400, 'test.com'); @@ -72,7 +72,7 @@ function it_combines_multiple_cookies_into_one_header(RequestInterface $request, }, function () {}); } - function it_does_not_load_cookie_if_expired(RequestInterface $request, UriInterface $uri, Promise $promise) + public function it_does_not_load_cookie_if_expired(RequestInterface $request, UriInterface $uri, Promise $promise) { $cookie = new Cookie('name', 'value', null, 'test.com', false, false, null, (new \DateTime())->modify('-1 day')); $this->cookieJar->addCookie($cookie); @@ -86,7 +86,7 @@ function it_does_not_load_cookie_if_expired(RequestInterface $request, UriInterf }, function () {}); } - function it_does_not_load_cookie_if_domain_does_not_match(RequestInterface $request, UriInterface $uri, Promise $promise) + public function it_does_not_load_cookie_if_domain_does_not_match(RequestInterface $request, UriInterface $uri, Promise $promise) { $cookie = new Cookie('name', 'value', 86400, 'test2.com'); $this->cookieJar->addCookie($cookie); @@ -103,7 +103,7 @@ function it_does_not_load_cookie_if_domain_does_not_match(RequestInterface $requ }, function () {}); } - function it_does_not_load_cookie_on_hackish_domains(RequestInterface $request, UriInterface $uri, Promise $promise) + public function it_does_not_load_cookie_on_hackish_domains(RequestInterface $request, UriInterface $uri, Promise $promise) { $hackishDomains = [ 'hacktest.com', @@ -126,7 +126,7 @@ function it_does_not_load_cookie_on_hackish_domains(RequestInterface $request, U } } - function it_loads_cookie_on_subdomains(RequestInterface $request, UriInterface $uri, Promise $promise) + public function it_loads_cookie_on_subdomains(RequestInterface $request, UriInterface $uri, Promise $promise) { $cookie = new Cookie('name', 'value', 86400, 'test.com'); $this->cookieJar->addCookie($cookie); @@ -144,7 +144,7 @@ function it_loads_cookie_on_subdomains(RequestInterface $request, UriInterface $ }, function () {}); } - function it_does_not_load_cookie_if_path_does_not_match(RequestInterface $request, UriInterface $uri, Promise $promise) + public function it_does_not_load_cookie_if_path_does_not_match(RequestInterface $request, UriInterface $uri, Promise $promise) { $cookie = new Cookie('name', 'value', 86400, 'test.com', '/sub'); $this->cookieJar->addCookie($cookie); @@ -162,7 +162,7 @@ function it_does_not_load_cookie_if_path_does_not_match(RequestInterface $reques }, function () {}); } - function it_does_not_load_cookie_when_cookie_is_secure(RequestInterface $request, UriInterface $uri, Promise $promise) + public function it_does_not_load_cookie_when_cookie_is_secure(RequestInterface $request, UriInterface $uri, Promise $promise) { $cookie = new Cookie('name', 'value', 86400, 'test.com', null, true); $this->cookieJar->addCookie($cookie); @@ -181,7 +181,7 @@ function it_does_not_load_cookie_when_cookie_is_secure(RequestInterface $request }, function () {}); } - function it_loads_cookie_when_cookie_is_secure(RequestInterface $request, UriInterface $uri, Promise $promise) + public function it_loads_cookie_when_cookie_is_secure(RequestInterface $request, UriInterface $uri, Promise $promise) { $cookie = new Cookie('name', 'value', 86400, 'test.com', null, true); $this->cookieJar->addCookie($cookie); @@ -200,7 +200,7 @@ function it_loads_cookie_when_cookie_is_secure(RequestInterface $request, UriInt }, function () {}); } - function it_saves_cookie(RequestInterface $request, ResponseInterface $response, UriInterface $uri) + public function it_saves_cookie(RequestInterface $request, ResponseInterface $response, UriInterface $uri) { $next = function () use ($response) { return new HttpFulfilledPromise($response->getWrappedObject()); @@ -208,7 +208,7 @@ function it_saves_cookie(RequestInterface $request, ResponseInterface $response, $response->hasHeader('Set-Cookie')->willReturn(true); $response->getHeader('Set-Cookie')->willReturn([ - 'cookie=value; expires=Tuesday, 31-Mar-99 07:42:12 GMT; Max-Age=60; path=/; domain=test.com; secure; HttpOnly' + 'cookie=value; expires=Tuesday, 31-Mar-99 07:42:12 GMT; Max-Age=60; path=/; domain=test.com; secure; HttpOnly', ]); $request->getUri()->willReturn($uri); @@ -220,7 +220,7 @@ function it_saves_cookie(RequestInterface $request, ResponseInterface $response, $promise->wait()->shouldReturnAnInstanceOf('Psr\Http\Message\ResponseInterface'); } - function it_throws_exception_on_invalid_expires_date( + public function it_throws_exception_on_invalid_expires_date( RequestInterface $request, ResponseInterface $response, UriInterface $uri @@ -231,7 +231,7 @@ function it_throws_exception_on_invalid_expires_date( $response->hasHeader('Set-Cookie')->willReturn(true); $response->getHeader('Set-Cookie')->willReturn([ - 'cookie=value; expires=i-am-an-invalid-date;' + 'cookie=value; expires=i-am-an-invalid-date;', ]); $request->getUri()->willReturn($uri); diff --git a/spec/Plugin/DecoderPluginSpec.php b/spec/Plugin/DecoderPluginSpec.php index 7543027..4de938c 100644 --- a/spec/Plugin/DecoderPluginSpec.php +++ b/spec/Plugin/DecoderPluginSpec.php @@ -12,25 +12,25 @@ class DecoderPluginSpec extends ObjectBehavior { - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\Plugin\DecoderPlugin'); } - function it_is_a_plugin() + public function it_is_a_plugin() { $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_decodes(RequestInterface $request, ResponseInterface $response, StreamInterface $stream) + public function it_decodes(RequestInterface $request, ResponseInterface $response, StreamInterface $stream) { - if(defined('HHVM_VERSION')) { + if (defined('HHVM_VERSION')) { throw new SkippingException('Skipping test on hhvm, as there is no chunk encoding on hhvm'); } $request->withHeader('TE', ['gzip', 'deflate', 'chunked'])->shouldBeCalled()->willReturn($request); $request->withHeader('Accept-Encoding', ['gzip', 'deflate'])->shouldBeCalled()->willReturn($request); - $next = function () use($response) { + $next = function () use ($response) { return new HttpFulfilledPromise($response->getWrappedObject()); }; @@ -48,11 +48,11 @@ function it_decodes(RequestInterface $request, ResponseInterface $response, Stre $this->handleRequest($request, $next, function () {}); } - function it_decodes_gzip(RequestInterface $request, ResponseInterface $response, StreamInterface $stream) + public function it_decodes_gzip(RequestInterface $request, ResponseInterface $response, StreamInterface $stream) { $request->withHeader('TE', ['gzip', 'deflate', 'chunked'])->shouldBeCalled()->willReturn($request); $request->withHeader('Accept-Encoding', ['gzip', 'deflate'])->shouldBeCalled()->willReturn($request); - $next = function () use($response) { + $next = function () use ($response) { return new HttpFulfilledPromise($response->getWrappedObject()); }; @@ -70,11 +70,11 @@ function it_decodes_gzip(RequestInterface $request, ResponseInterface $response, $this->handleRequest($request, $next, function () {}); } - function it_decodes_deflate(RequestInterface $request, ResponseInterface $response, StreamInterface $stream) + public function it_decodes_deflate(RequestInterface $request, ResponseInterface $response, StreamInterface $stream) { $request->withHeader('TE', ['gzip', 'deflate', 'chunked'])->shouldBeCalled()->willReturn($request); $request->withHeader('Accept-Encoding', ['gzip', 'deflate'])->shouldBeCalled()->willReturn($request); - $next = function () use($response) { + $next = function () use ($response) { return new HttpFulfilledPromise($response->getWrappedObject()); }; @@ -92,13 +92,13 @@ function it_decodes_deflate(RequestInterface $request, ResponseInterface $respon $this->handleRequest($request, $next, function () {}); } - function it_does_not_decode_with_content_encoding(RequestInterface $request, ResponseInterface $response) + public function it_does_not_decode_with_content_encoding(RequestInterface $request, ResponseInterface $response) { $this->beConstructedWith(['use_content_encoding' => false]); $request->withHeader('TE', ['gzip', 'deflate', 'chunked'])->shouldBeCalled()->willReturn($request); $request->withHeader('Accept-Encoding', ['gzip', 'deflate'])->shouldNotBeCalled(); - $next = function () use($response) { + $next = function () use ($response) { return new HttpFulfilledPromise($response->getWrappedObject()); }; diff --git a/spec/Plugin/ErrorPluginSpec.php b/spec/Plugin/ErrorPluginSpec.php index 20fcc25..5a9e90a 100644 --- a/spec/Plugin/ErrorPluginSpec.php +++ b/spec/Plugin/ErrorPluginSpec.php @@ -10,22 +10,22 @@ class ErrorPluginSpec extends ObjectBehavior { - function it_is_initializable() + public function it_is_initializable() { $this->beAnInstanceOf('Http\Client\Common\Plugin\ErrorPlugin'); } - function it_is_a_plugin() + public function it_is_a_plugin() { $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_throw_client_error_exception_on_4xx_error(RequestInterface $request, ResponseInterface $response) + public function it_throw_client_error_exception_on_4xx_error(RequestInterface $request, ResponseInterface $response) { $response->getStatusCode()->willReturn('400'); $response->getReasonPhrase()->willReturn('Bad request'); - $next = function (RequestInterface $receivedRequest) use($request, $response) { + $next = function (RequestInterface $receivedRequest) use ($request, $response) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($response->getWrappedObject()); } @@ -36,14 +36,14 @@ function it_throw_client_error_exception_on_4xx_error(RequestInterface $request, $promise->shouldThrow('Http\Client\Common\Exception\ClientErrorException')->duringWait(); } - function it_does_not_throw_client_error_exception_on_4xx_error_if_only_server_exception(RequestInterface $request, ResponseInterface $response) + public function it_does_not_throw_client_error_exception_on_4xx_error_if_only_server_exception(RequestInterface $request, ResponseInterface $response) { $this->beConstructedWith(['only_server_exception' => true]); $response->getStatusCode()->willReturn('400'); $response->getReasonPhrase()->willReturn('Bad request'); - $next = function (RequestInterface $receivedRequest) use($request, $response) { + $next = function (RequestInterface $receivedRequest) use ($request, $response) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($response->getWrappedObject()); } @@ -52,12 +52,12 @@ function it_does_not_throw_client_error_exception_on_4xx_error_if_only_server_ex $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); } - function it_throw_server_error_exception_on_5xx_error(RequestInterface $request, ResponseInterface $response) + public function it_throw_server_error_exception_on_5xx_error(RequestInterface $request, ResponseInterface $response) { $response->getStatusCode()->willReturn('500'); $response->getReasonPhrase()->willReturn('Server error'); - $next = function (RequestInterface $receivedRequest) use($request, $response) { + $next = function (RequestInterface $receivedRequest) use ($request, $response) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($response->getWrappedObject()); } @@ -68,11 +68,11 @@ function it_throw_server_error_exception_on_5xx_error(RequestInterface $request, $promise->shouldThrow('Http\Client\Common\Exception\ServerErrorException')->duringWait(); } - function it_returns_response(RequestInterface $request, ResponseInterface $response) + public function it_returns_response(RequestInterface $request, ResponseInterface $response) { $response->getStatusCode()->willReturn('200'); - $next = function (RequestInterface $receivedRequest) use($request, $response) { + $next = function (RequestInterface $receivedRequest) use ($request, $response) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($response->getWrappedObject()); } diff --git a/spec/Plugin/HeaderAppendPluginSpec.php b/spec/Plugin/HeaderAppendPluginSpec.php index 24b8565..bb10de1 100644 --- a/spec/Plugin/HeaderAppendPluginSpec.php +++ b/spec/Plugin/HeaderAppendPluginSpec.php @@ -2,11 +2,8 @@ namespace spec\Http\Client\Common\Plugin; -use PhpSpec\Exception\Example\SkippingException; use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\StreamInterface; use PhpSpec\ObjectBehavior; -use Prophecy\Argument; class HeaderAppendPluginSpec extends ObjectBehavior { @@ -25,8 +22,8 @@ public function it_is_a_plugin() public function it_appends_the_header(RequestInterface $request) { $this->beConstructedWith([ - 'foo'=>'bar', - 'baz'=>'qux' + 'foo' => 'bar', + 'baz' => 'qux', ]); $request->withAddedHeader('foo', 'bar')->shouldBeCalled()->willReturn($request); diff --git a/spec/Plugin/HeaderDefaultsPluginSpec.php b/spec/Plugin/HeaderDefaultsPluginSpec.php index 341f1a5..cd407e3 100644 --- a/spec/Plugin/HeaderDefaultsPluginSpec.php +++ b/spec/Plugin/HeaderDefaultsPluginSpec.php @@ -2,11 +2,8 @@ namespace spec\Http\Client\Common\Plugin; -use PhpSpec\Exception\Example\SkippingException; use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\StreamInterface; use PhpSpec\ObjectBehavior; -use Prophecy\Argument; class HeaderDefaultsPluginSpec extends ObjectBehavior { @@ -26,7 +23,7 @@ public function it_sets_the_default_header(RequestInterface $request) { $this->beConstructedWith([ 'foo' => 'bar', - 'baz' => 'qux' + 'baz' => 'qux', ]); $request->hasHeader('foo')->shouldBeCalled()->willReturn(false); diff --git a/spec/Plugin/HeaderRemovePluginSpec.php b/spec/Plugin/HeaderRemovePluginSpec.php index 9ea2752..ec6b069 100644 --- a/spec/Plugin/HeaderRemovePluginSpec.php +++ b/spec/Plugin/HeaderRemovePluginSpec.php @@ -2,11 +2,8 @@ namespace spec\Http\Client\Common\Plugin; -use PhpSpec\Exception\Example\SkippingException; use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\StreamInterface; use PhpSpec\ObjectBehavior; -use Prophecy\Argument; class HeaderRemovePluginSpec extends ObjectBehavior { @@ -26,7 +23,7 @@ public function it_removes_the_header(RequestInterface $request) { $this->beConstructedWith([ 'foo', - 'baz' + 'baz', ]); $request->hasHeader('foo')->shouldBeCalled()->willReturn(false); diff --git a/spec/Plugin/HeaderSetPluginSpec.php b/spec/Plugin/HeaderSetPluginSpec.php index f4a340c..4e4efd0 100644 --- a/spec/Plugin/HeaderSetPluginSpec.php +++ b/spec/Plugin/HeaderSetPluginSpec.php @@ -2,11 +2,8 @@ namespace spec\Http\Client\Common\Plugin; -use PhpSpec\Exception\Example\SkippingException; use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\StreamInterface; use PhpSpec\ObjectBehavior; -use Prophecy\Argument; class HeaderSetPluginSpec extends ObjectBehavior { @@ -25,8 +22,8 @@ public function it_is_a_plugin() public function it_set_the_header(RequestInterface $request) { $this->beConstructedWith([ - 'foo'=>'bar', - 'baz'=>'qux' + 'foo' => 'bar', + 'baz' => 'qux', ]); $request->withHeader('foo', 'bar')->shouldBeCalled()->willReturn($request); diff --git a/spec/Plugin/HistoryPluginSpec.php b/spec/Plugin/HistoryPluginSpec.php index 24e7f51..77682a7 100644 --- a/spec/Plugin/HistoryPluginSpec.php +++ b/spec/Plugin/HistoryPluginSpec.php @@ -13,24 +13,24 @@ class HistoryPluginSpec extends ObjectBehavior { - function let(Journal $journal) + public function let(Journal $journal) { $this->beConstructedWith($journal); } - function it_is_initializable() + public function it_is_initializable() { $this->beAnInstanceOf('Http\Client\Common\Plugin\JournalPlugin'); } - function it_is_a_plugin() + public function it_is_a_plugin() { $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_records_success(Journal $journal, RequestInterface $request, ResponseInterface $response) + public function it_records_success(Journal $journal, RequestInterface $request, ResponseInterface $response) { - $next = function (RequestInterface $receivedRequest) use($request, $response) { + $next = function (RequestInterface $receivedRequest) use ($request, $response) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($response->getWrappedObject()); } @@ -41,10 +41,10 @@ function it_records_success(Journal $journal, RequestInterface $request, Respons $this->handleRequest($request, $next, function () {}); } - function it_records_failure(Journal $journal, RequestInterface $request) + public function it_records_failure(Journal $journal, RequestInterface $request) { $exception = new TransferException(); - $next = function (RequestInterface $receivedRequest) use($request, $exception) { + $next = function (RequestInterface $receivedRequest) use ($request, $exception) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpRejectedPromise($exception); } diff --git a/spec/Plugin/QueryDefaultsPluginSpec.php b/spec/Plugin/QueryDefaultsPluginSpec.php index 82d9125..aa50f81 100644 --- a/spec/Plugin/QueryDefaultsPluginSpec.php +++ b/spec/Plugin/QueryDefaultsPluginSpec.php @@ -2,7 +2,6 @@ namespace spec\Http\Client\Common\Plugin; -use Http\Client\Common\Plugin; use Psr\Http\Message\RequestInterface; use PhpSpec\ObjectBehavior; use Psr\Http\Message\UriInterface; diff --git a/spec/Plugin/RedirectPluginSpec.php b/spec/Plugin/RedirectPluginSpec.php index 97197e1..283bfb5 100644 --- a/spec/Plugin/RedirectPluginSpec.php +++ b/spec/Plugin/RedirectPluginSpec.php @@ -13,17 +13,17 @@ class RedirectPluginSpec extends ObjectBehavior { - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\Plugin\RedirectPlugin'); } - function it_is_a_plugin() + public function it_is_a_plugin() { $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_redirects_on_302( + public function it_redirects_on_302( UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, @@ -48,14 +48,13 @@ function it_redirects_on_302( $modifiedRequest->getUri()->willReturn($uriRedirect); $modifiedRequest->getMethod()->willReturn('GET'); - - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } }; - $first = function (RequestInterface $receivedRequest) use($modifiedRequest, $promise) { + $first = function (RequestInterface $receivedRequest) use ($modifiedRequest, $promise) { if (Argument::is($modifiedRequest->getWrappedObject())->scoreArgument($receivedRequest)) { return $promise->getWrappedObject(); } @@ -69,7 +68,7 @@ function it_redirects_on_302( $finalPromise->wait()->shouldReturn($finalResponse); } - function it_use_storage_on_301(UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, RequestInterface $modifiedRequest) + public function it_use_storage_on_301(UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, RequestInterface $modifiedRequest) { $this->beAnInstanceOf('spec\Http\Client\Common\Plugin\RedirectPluginStub'); $this->beConstructedWith($uriRedirect, '/original', '301'); @@ -90,7 +89,7 @@ function it_use_storage_on_301(UriInterface $uri, UriInterface $uriRedirect, Req $this->handleRequest($request, $next, function () {}); } - function it_stores_a_301( + public function it_stores_a_301( UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, @@ -99,7 +98,6 @@ function it_stores_a_301( ResponseInterface $finalResponse, Promise $promise ) { - $this->beAnInstanceOf('spec\Http\Client\Common\Plugin\RedirectPluginStub'); $this->beConstructedWith($uriRedirect, '', '301'); @@ -121,13 +119,13 @@ function it_stores_a_301( $uriRedirect->__toString()->willReturn('/redirect'); - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } }; - $first = function (RequestInterface $receivedRequest) use($modifiedRequest, $promise) { + $first = function (RequestInterface $receivedRequest) use ($modifiedRequest, $promise) { if (Argument::is($modifiedRequest->getWrappedObject())->scoreArgument($receivedRequest)) { return $promise->getWrappedObject(); } @@ -140,7 +138,7 @@ function it_stores_a_301( $this->hasStorage('/301-url')->shouldReturn(true); } - function it_replace_full_url( + public function it_replace_full_url( UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, @@ -171,13 +169,13 @@ function it_replace_full_url( $uriRedirect->__toString()->willReturn('/redirect'); - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } }; - $first = function (RequestInterface $receivedRequest) use($modifiedRequest, $promise) { + $first = function (RequestInterface $receivedRequest) use ($modifiedRequest, $promise) { if (Argument::is($modifiedRequest->getWrappedObject())->scoreArgument($receivedRequest)) { return $promise->getWrappedObject(); } @@ -189,9 +187,9 @@ function it_replace_full_url( $this->handleRequest($request, $next, $first); } - function it_throws_http_exception_on_no_location(RequestInterface $request, UriInterface $uri, ResponseInterface $responseRedirect) + public function it_throws_http_exception_on_no_location(RequestInterface $request, UriInterface $uri, ResponseInterface $responseRedirect) { - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } @@ -207,9 +205,9 @@ function it_throws_http_exception_on_no_location(RequestInterface $request, UriI $promise->shouldThrow('Http\Client\Exception\HttpException')->duringWait(); } - function it_throws_http_exception_on_invalid_location(RequestInterface $request, UriInterface $uri, ResponseInterface $responseRedirect) + public function it_throws_http_exception_on_invalid_location(RequestInterface $request, UriInterface $uri, ResponseInterface $responseRedirect) { - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } @@ -227,9 +225,9 @@ function it_throws_http_exception_on_invalid_location(RequestInterface $request, $promise->shouldThrow('Http\Client\Exception\HttpException')->duringWait(); } - function it_throw_multi_redirect_exception_on_300(RequestInterface $request, ResponseInterface $responseRedirect) + public function it_throw_multi_redirect_exception_on_300(RequestInterface $request, ResponseInterface $responseRedirect) { - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } @@ -243,9 +241,9 @@ function it_throw_multi_redirect_exception_on_300(RequestInterface $request, Res $promise->shouldThrow('Http\Client\Common\Exception\MultipleRedirectionException')->duringWait(); } - function it_throw_multi_redirect_exception_on_300_if_no_location(RequestInterface $request, ResponseInterface $responseRedirect) + public function it_throw_multi_redirect_exception_on_300_if_no_location(RequestInterface $request, ResponseInterface $responseRedirect) { - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } @@ -259,7 +257,7 @@ function it_throw_multi_redirect_exception_on_300_if_no_location(RequestInterfac $promise->shouldThrow('Http\Client\Common\Exception\MultipleRedirectionException')->duringWait(); } - function it_switch_method_for_302( + public function it_switch_method_for_302( UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, @@ -288,13 +286,13 @@ function it_switch_method_for_302( $modifiedRequest->getMethod()->willReturn('POST'); $modifiedRequest->withMethod('GET')->willReturn($modifiedRequest); - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } }; - $first = function (RequestInterface $receivedRequest) use($modifiedRequest, $promise) { + $first = function (RequestInterface $receivedRequest) use ($modifiedRequest, $promise) { if (Argument::is($modifiedRequest->getWrappedObject())->scoreArgument($receivedRequest)) { return $promise->getWrappedObject(); } @@ -306,7 +304,7 @@ function it_switch_method_for_302( $this->handleRequest($request, $next, $first); } - function it_clears_headers( + public function it_clears_headers( UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, @@ -338,13 +336,13 @@ function it_clears_headers( $modifiedRequest->withoutHeader('Cookie')->willReturn($modifiedRequest); $modifiedRequest->getUri()->willReturn($uriRedirect); - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } }; - $first = function (RequestInterface $receivedRequest) use($modifiedRequest, $promise) { + $first = function (RequestInterface $receivedRequest) use ($modifiedRequest, $promise) { if (Argument::is($modifiedRequest->getWrappedObject())->scoreArgument($receivedRequest)) { return $promise->getWrappedObject(); } @@ -356,12 +354,12 @@ function it_clears_headers( $this->handleRequest($request, $next, $first); } - function it_throws_circular_redirection_exception(UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, ResponseInterface $responseRedirect, RequestInterface $modifiedRequest) + public function it_throws_circular_redirection_exception(UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, ResponseInterface $responseRedirect, RequestInterface $modifiedRequest) { - $first = function() {}; + $first = function () {}; $this->beAnInstanceOf('spec\Http\Client\Common\Plugin\RedirectPluginStubCircular'); - $this->beConstructedWith(spl_object_hash((object)$first)); + $this->beConstructedWith(spl_object_hash((object) $first)); $request->getUri()->willReturn($uri); $uri->__toString()->willReturn('/original'); @@ -379,7 +377,7 @@ function it_throws_circular_redirection_exception(UriInterface $uri, UriInterfac $uriRedirect->__toString()->willReturn('/redirect'); $modifiedRequest->getMethod()->willReturn('GET'); - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } @@ -390,7 +388,7 @@ function it_throws_circular_redirection_exception(UriInterface $uri, UriInterfac $promise->shouldThrow('Http\Client\Common\Exception\CircularRedirectionException')->duringWait(); } - function it_redirects_http_to_https( + public function it_redirects_http_to_https( UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, @@ -417,13 +415,13 @@ function it_redirects_http_to_https( $modifiedRequest->getUri()->willReturn($uriRedirect); $modifiedRequest->getMethod()->willReturn('GET'); - $next = function (RequestInterface $receivedRequest) use($request, $responseRedirect) { + $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); } }; - $first = function (RequestInterface $receivedRequest) use($modifiedRequest, $promise) { + $first = function (RequestInterface $receivedRequest) use ($modifiedRequest, $promise) { if (Argument::is($modifiedRequest->getWrappedObject())->scoreArgument($receivedRequest)) { return $promise->getWrappedObject(); } @@ -446,7 +444,7 @@ public function __construct(UriInterface $uri, $storedUrl, $status, array $confi $this->redirectStorage[$storedUrl] = [ 'uri' => $uri, - 'status' => $status + 'status' => $status, ]; } @@ -462,8 +460,8 @@ public function __construct($chainHash) { $this->circularDetection = [ $chainHash => [ - '/redirect' - ] + '/redirect', + ], ]; } } diff --git a/spec/Plugin/RequestMatcherPluginSpec.php b/spec/Plugin/RequestMatcherPluginSpec.php index 4fe9aea..bd4e7e4 100644 --- a/spec/Plugin/RequestMatcherPluginSpec.php +++ b/spec/Plugin/RequestMatcherPluginSpec.php @@ -11,22 +11,22 @@ class RequestMatcherPluginSpec extends ObjectBehavior { - function let(RequestMatcher $requestMatcher, Plugin $plugin) + public function let(RequestMatcher $requestMatcher, Plugin $plugin) { $this->beConstructedWith($requestMatcher, $plugin); } - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\Plugin\RequestMatcherPlugin'); } - function it_is_a_plugin() + public function it_is_a_plugin() { $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_matches_a_request_and_delegates_to_plugin( + public function it_matches_a_request_and_delegates_to_plugin( RequestInterface $request, RequestMatcher $requestMatcher, Plugin $plugin @@ -37,7 +37,7 @@ function it_matches_a_request_and_delegates_to_plugin( $this->handleRequest($request, function () {}, function () {}); } - function it_does_not_match_a_request( + public function it_does_not_match_a_request( RequestInterface $request, RequestMatcher $requestMatcher, Plugin $plugin, @@ -46,7 +46,7 @@ function it_does_not_match_a_request( $requestMatcher->matches($request)->willReturn(false); $plugin->handleRequest($request, Argument::type('callable'), Argument::type('callable'))->shouldNotBeCalled(); - $next = function (RequestInterface $request) use($promise) { + $next = function (RequestInterface $request) use ($promise) { return $promise->getWrappedObject(); }; diff --git a/spec/Plugin/RetryPluginSpec.php b/spec/Plugin/RetryPluginSpec.php index 37800ae..c439cad 100644 --- a/spec/Plugin/RetryPluginSpec.php +++ b/spec/Plugin/RetryPluginSpec.php @@ -12,19 +12,19 @@ class RetryPluginSpec extends ObjectBehavior { - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\Plugin\RetryPlugin'); } - function it_is_a_plugin() + public function it_is_a_plugin() { $this->shouldImplement('Http\Client\Common\Plugin'); } - function it_returns_response(RequestInterface $request, ResponseInterface $response) + public function it_returns_response(RequestInterface $request, ResponseInterface $response) { - $next = function (RequestInterface $receivedRequest) use($request, $response) { + $next = function (RequestInterface $receivedRequest) use ($request, $response) { if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { return new HttpFulfilledPromise($response->getWrappedObject()); } @@ -33,20 +33,20 @@ function it_returns_response(RequestInterface $request, ResponseInterface $respo $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); } - function it_throws_exception_on_multiple_exceptions(RequestInterface $request) + public function it_throws_exception_on_multiple_exceptions(RequestInterface $request) { $exception1 = new Exception\NetworkException('Exception 1', $request->getWrappedObject()); $exception2 = new Exception\NetworkException('Exception 2', $request->getWrappedObject()); $count = 0; - $next = function (RequestInterface $receivedRequest) use($request, $exception1, $exception2, &$count) { - $count++; + $next = function (RequestInterface $receivedRequest) use ($request, $exception1, $exception2, &$count) { + ++$count; if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { - if ($count == 1) { + if (1 == $count) { return new HttpRejectedPromise($exception1); } - if ($count == 2) { + if (2 == $count) { return new HttpRejectedPromise($exception2); } } @@ -57,19 +57,19 @@ function it_throws_exception_on_multiple_exceptions(RequestInterface $request) $promise->shouldThrow($exception2)->duringWait(); } - function it_returns_response_on_second_try(RequestInterface $request, ResponseInterface $response) + public function it_returns_response_on_second_try(RequestInterface $request, ResponseInterface $response) { $exception = new Exception\NetworkException('Exception 1', $request->getWrappedObject()); $count = 0; - $next = function (RequestInterface $receivedRequest) use($request, $exception, $response, &$count) { - $count++; + $next = function (RequestInterface $receivedRequest) use ($request, $exception, $response, &$count) { + ++$count; if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { - if ($count == 1) { + if (1 == $count) { return new HttpRejectedPromise($exception); } - if ($count == 2) { + if (2 == $count) { return new HttpFulfilledPromise($response->getWrappedObject()); } } @@ -80,19 +80,19 @@ function it_returns_response_on_second_try(RequestInterface $request, ResponseIn $promise->wait()->shouldReturn($response); } - function it_does_not_keep_history_of_old_failure(RequestInterface $request, ResponseInterface $response) + public function it_does_not_keep_history_of_old_failure(RequestInterface $request, ResponseInterface $response) { $exception = new Exception\NetworkException('Exception 1', $request->getWrappedObject()); $count = 0; - $next = function (RequestInterface $receivedRequest) use($request, $exception, $response, &$count) { - $count++; + $next = function (RequestInterface $receivedRequest) use ($request, $exception, $response, &$count) { + ++$count; if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { - if ($count % 2 == 1) { + if (1 == $count % 2) { return new HttpRejectedPromise($exception); } - if ($count % 2 == 0) { + if (0 == $count % 2) { return new HttpFulfilledPromise($response->getWrappedObject()); } } @@ -102,7 +102,7 @@ function it_does_not_keep_history_of_old_failure(RequestInterface $request, Resp $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); } - function it_has_an_exponential_default_delay(RequestInterface $request, Exception\HttpException $exception) + public function it_has_an_exponential_default_delay(RequestInterface $request, Exception\HttpException $exception) { $this->defaultDelay($request, $exception, 0)->shouldBe(500000); $this->defaultDelay($request, $exception, 1)->shouldBe(1000000); diff --git a/spec/PluginClientFactorySpec.php b/spec/PluginClientFactorySpec.php index 1f8d9e8..fe7e076 100644 --- a/spec/PluginClientFactorySpec.php +++ b/spec/PluginClientFactorySpec.php @@ -7,19 +7,19 @@ class PluginClientFactorySpec extends ObjectBehavior { - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\PluginClientFactory'); } - function it_returns_a_plugin_client(HttpClient $httpClient) + public function it_returns_a_plugin_client(HttpClient $httpClient) { $client = $this->createClient($httpClient); $client->shouldHaveType('Http\Client\Common\PluginClient'); } - function it_does_not_construct_plugin_client_with_client_name_option(HttpClient $httpClient) + public function it_does_not_construct_plugin_client_with_client_name_option(HttpClient $httpClient) { $this->createClient($httpClient, [], ['client_name' => 'Default']); } diff --git a/spec/PluginClientSpec.php b/spec/PluginClientSpec.php index 88406ae..50df636 100644 --- a/spec/PluginClientSpec.php +++ b/spec/PluginClientSpec.php @@ -4,7 +4,6 @@ use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; -use Http\Client\Common\FlexibleHttpClient; use Http\Client\Common\Plugin; use Http\Promise\Promise; use Prophecy\Argument; @@ -14,34 +13,34 @@ class PluginClientSpec extends ObjectBehavior { - function let(HttpClient $httpClient) + public function let(HttpClient $httpClient) { $this->beConstructedWith($httpClient); } - function it_is_initializable() + public function it_is_initializable() { $this->shouldHaveType('Http\Client\Common\PluginClient'); } - function it_is_an_http_client() + public function it_is_an_http_client() { $this->shouldImplement('Http\Client\HttpClient'); } - function it_is_an_http_async_client() + public function it_is_an_http_async_client() { $this->shouldImplement('Http\Client\HttpAsyncClient'); } - function it_sends_request_with_underlying_client(HttpClient $httpClient, RequestInterface $request, ResponseInterface $response) + public function it_sends_request_with_underlying_client(HttpClient $httpClient, RequestInterface $request, ResponseInterface $response) { $httpClient->sendRequest($request)->willReturn($response); $this->sendRequest($request)->shouldReturn($response); } - function it_sends_async_request_with_underlying_client(HttpAsyncClient $httpAsyncClient, RequestInterface $request, Promise $promise) + public function it_sends_async_request_with_underlying_client(HttpAsyncClient $httpAsyncClient, RequestInterface $request, Promise $promise) { $httpAsyncClient->sendAsyncRequest($request)->willReturn($promise); @@ -49,7 +48,7 @@ function it_sends_async_request_with_underlying_client(HttpAsyncClient $httpAsyn $this->sendAsyncRequest($request)->shouldReturn($promise); } - function it_sends_async_request_if_no_send_request(HttpAsyncClient $httpAsyncClient, RequestInterface $request, ResponseInterface $response, Promise $promise) + public function it_sends_async_request_if_no_send_request(HttpAsyncClient $httpAsyncClient, RequestInterface $request, ResponseInterface $response, Promise $promise) { $this->beConstructedWith($httpAsyncClient); $httpAsyncClient->sendAsyncRequest($request)->willReturn($promise); @@ -58,7 +57,7 @@ function it_sends_async_request_if_no_send_request(HttpAsyncClient $httpAsyncCli $this->sendRequest($request)->shouldReturn($response); } - function it_prefers_send_request($client, RequestInterface $request, ResponseInterface $response) + public function it_prefers_send_request($client, RequestInterface $request, ResponseInterface $response) { $client->implement('Http\Client\HttpClient'); $client->implement('Http\Client\HttpAsyncClient'); @@ -70,7 +69,7 @@ function it_prefers_send_request($client, RequestInterface $request, ResponseInt $this->sendRequest($request)->shouldReturn($response); } - function it_throws_loop_exception(HttpClient $httpClient, RequestInterface $request, Plugin $plugin) + public function it_throws_loop_exception(HttpClient $httpClient, RequestInterface $request, Plugin $plugin) { $plugin ->handleRequest( diff --git a/src/HttpClientRouter.php b/src/HttpClientRouter.php index fa32c56..ac7699c 100644 --- a/src/HttpClientRouter.php +++ b/src/HttpClientRouter.php @@ -62,7 +62,7 @@ public function addClient($client, RequestMatcher $requestMatcher) * * @return HttpClient|HttpAsyncClient */ - protected function chooseHttpClient(RequestInterface $request) + private function chooseHttpClient(RequestInterface $request) { foreach ($this->clients as $client) { if ($client['matcher']->matches($request)) { diff --git a/src/Plugin.php b/src/Plugin.php index 89a2a62..6248fc7 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -26,7 +26,7 @@ interface Plugin * @param callable $next Next middleware in the chain, the request is passed as the first argument * @param callable $first First middleware in the chain, used to to restart a request * - * @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception (The same as HttpAsyncClient). + * @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception (The same as HttpAsyncClient) */ public function handleRequest(RequestInterface $request, callable $next, callable $first); } diff --git a/src/Plugin/BaseUriPlugin.php b/src/Plugin/BaseUriPlugin.php index 2c2a775..669c308 100644 --- a/src/Plugin/BaseUriPlugin.php +++ b/src/Plugin/BaseUriPlugin.php @@ -24,7 +24,7 @@ final class BaseUriPlugin implements Plugin private $addPathPlugin = null; /** - * @param UriInterface $uri Has to contain a host name and cans have a path. + * @param UriInterface $uri Has to contain a host name and cans have a path * @param array $hostConfig Config for AddHostPlugin. @see AddHostPlugin::configureOptions */ public function __construct(UriInterface $uri, array $hostConfig = []) diff --git a/src/Plugin/ContentTypePlugin.php b/src/Plugin/ContentTypePlugin.php index 8ef1d62..d0bfa8d 100644 --- a/src/Plugin/ContentTypePlugin.php +++ b/src/Plugin/ContentTypePlugin.php @@ -22,19 +22,19 @@ final class ContentTypePlugin implements Plugin * true skip the content type detection * false detect the content type (default value) */ - protected $skipDetection; + private $skipDetection; /** * Determine the size stream limit for which the detection as to be skipped (default to 16Mb). * * @var int */ - protected $sizeLimit; + private $sizeLimit; /** * @param array $config { * - * @var bool $skip_detection True skip detection if stream size is bigger than $size_limit. + * @var bool $skip_detection true skip detection if stream size is bigger than $size_limit * @var int $size_limit size stream limit for which the detection as to be skipped. * } */ diff --git a/src/Plugin/ErrorPlugin.php b/src/Plugin/ErrorPlugin.php index bcc1c67..4fd7201 100644 --- a/src/Plugin/ErrorPlugin.php +++ b/src/Plugin/ErrorPlugin.php @@ -66,7 +66,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl * * @return ResponseInterface If status code is not in 4xx or 5xx return response */ - protected function transformResponseToException(RequestInterface $request, ResponseInterface $response) + private function transformResponseToException(RequestInterface $request, ResponseInterface $response) { if (!$this->onlyServerException && $response->getStatusCode() >= 400 && $response->getStatusCode() < 500) { throw new ClientErrorException($response->getReasonPhrase(), $request, $response); diff --git a/src/Plugin/RetryPlugin.php b/src/Plugin/RetryPlugin.php index 8446246..0a5b4e7 100644 --- a/src/Plugin/RetryPlugin.php +++ b/src/Plugin/RetryPlugin.php @@ -44,8 +44,8 @@ final class RetryPlugin implements Plugin /** * @param array $config { * - * @var int $retries Number of retries to attempt if an exception occurs before letting the exception bubble up. - * @var callable $decider A callback that gets a request and an exception to decide after a failure whether the request should be retried. + * @var int $retries Number of retries to attempt if an exception occurs before letting the exception bubble up + * @var callable $decider A callback that gets a request and an exception to decide after a failure whether the request should be retried * @var callable $delay A callback that gets a request, an exception and the number of retries and returns how many microseconds we should wait before trying again. * } */ From f966926c4cb3d49657903e73f02b09a54e80d68b Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Tue, 20 Nov 2018 16:40:45 +0100 Subject: [PATCH 06/28] Add rules to cleanup PHPDocs --- .php_cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.php_cs b/.php_cs index 7da3701..7039b1e 100644 --- a/.php_cs +++ b/.php_cs @@ -7,6 +7,8 @@ $config->setRules([ 'array_syntax' => [ 'syntax' => 'short', ], + 'no_empty_phpdoc' => true, + 'no_superfluous_phpdoc_tags' => true, ]); $finder = PhpCsFixer\Finder::create(); From 720a0cde7d1a608a70513c784cbc0728e8145a92 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Tue, 20 Nov 2018 16:43:55 +0100 Subject: [PATCH 07/28] Remove unuseful PHPDoc automatically --- src/BatchClient.php | 3 --- src/BatchResult.php | 14 -------------- src/EmulatedHttpAsyncClient.php | 3 --- src/EmulatedHttpClient.php | 3 --- src/Exception/BatchException.php | 3 --- src/HttpClientRouter.php | 3 --- src/HttpMethodsClient.php | 11 +---------- src/Plugin.php | 5 ++--- src/Plugin/AddHostPlugin.php | 6 +----- src/Plugin/AddPathPlugin.php | 3 --- src/Plugin/AuthenticationPlugin.php | 3 --- src/Plugin/CookiePlugin.php | 4 ---- src/Plugin/DecoderPlugin.php | 3 +-- src/Plugin/HistoryPlugin.php | 3 --- src/Plugin/RequestMatcherPlugin.php | 4 ---- src/Plugin/RetryPlugin.php | 4 +--- src/PluginClient.php | 2 -- src/PluginClientFactory.php | 2 -- 18 files changed, 6 insertions(+), 73 deletions(-) diff --git a/src/BatchClient.php b/src/BatchClient.php index 2a39904..7ddba4e 100644 --- a/src/BatchClient.php +++ b/src/BatchClient.php @@ -22,9 +22,6 @@ class BatchClient implements HttpClient */ private $client; - /** - * @param HttpClient $client - */ public function __construct(HttpClient $client) { $this->client = $client; diff --git a/src/BatchResult.php b/src/BatchResult.php index 710611d..3f8a2f0 100644 --- a/src/BatchResult.php +++ b/src/BatchResult.php @@ -58,8 +58,6 @@ public function getResponses() /** * Checks if there is a successful response for a request. * - * @param RequestInterface $request - * * @return bool */ public function isSuccessful(RequestInterface $request) @@ -70,8 +68,6 @@ public function isSuccessful(RequestInterface $request) /** * Returns the response for a successful request. * - * @param RequestInterface $request - * * @return ResponseInterface * * @throws \UnexpectedValueException If request was not part of the batch or failed @@ -88,9 +84,6 @@ public function getResponseFor(RequestInterface $request) /** * Adds a response in an immutable way. * - * @param RequestInterface $request - * @param ResponseInterface $response - * * @return BatchResult the new BatchResult with this request-response pair added to it */ public function addResponse(RequestInterface $request, ResponseInterface $response) @@ -130,8 +123,6 @@ public function getExceptions() /** * Checks if there is an exception for a request, meaning the request failed. * - * @param RequestInterface $request - * * @return bool */ public function isFailed(RequestInterface $request) @@ -142,8 +133,6 @@ public function isFailed(RequestInterface $request) /** * Returns the exception for a failed request. * - * @param RequestInterface $request - * * @return Exception * * @throws \UnexpectedValueException If request was not part of the batch or was successful @@ -160,9 +149,6 @@ public function getExceptionFor(RequestInterface $request) /** * Adds an exception in an immutable way. * - * @param RequestInterface $request - * @param Exception $exception - * * @return BatchResult the new BatchResult with this request-exception pair added to it */ public function addException(RequestInterface $request, Exception $exception) diff --git a/src/EmulatedHttpAsyncClient.php b/src/EmulatedHttpAsyncClient.php index 1b16316..64acd59 100644 --- a/src/EmulatedHttpAsyncClient.php +++ b/src/EmulatedHttpAsyncClient.php @@ -17,9 +17,6 @@ class EmulatedHttpAsyncClient implements HttpClient, HttpAsyncClient use HttpAsyncClientEmulator; use HttpClientDecorator; - /** - * @param HttpClient $httpClient - */ public function __construct(HttpClient $httpClient) { $this->httpClient = $httpClient; diff --git a/src/EmulatedHttpClient.php b/src/EmulatedHttpClient.php index 01046c8..3635e9f 100644 --- a/src/EmulatedHttpClient.php +++ b/src/EmulatedHttpClient.php @@ -17,9 +17,6 @@ class EmulatedHttpClient implements HttpClient, HttpAsyncClient use HttpAsyncClientDecorator; use HttpClientEmulator; - /** - * @param HttpAsyncClient $httpAsyncClient - */ public function __construct(HttpAsyncClient $httpAsyncClient) { $this->httpAsyncClient = $httpAsyncClient; diff --git a/src/Exception/BatchException.php b/src/Exception/BatchException.php index 66a9271..8620f9d 100644 --- a/src/Exception/BatchException.php +++ b/src/Exception/BatchException.php @@ -19,9 +19,6 @@ final class BatchException extends TransferException */ private $result; - /** - * @param BatchResult $result - */ public function __construct(BatchResult $result) { $this->result = $result; diff --git a/src/HttpClientRouter.php b/src/HttpClientRouter.php index ac7699c..00ca15f 100644 --- a/src/HttpClientRouter.php +++ b/src/HttpClientRouter.php @@ -45,7 +45,6 @@ public function sendAsyncRequest(RequestInterface $request) * Add a client to the router. * * @param HttpClient|HttpAsyncClient $client - * @param RequestMatcher $requestMatcher */ public function addClient($client, RequestMatcher $requestMatcher) { @@ -58,8 +57,6 @@ public function addClient($client, RequestMatcher $requestMatcher) /** * Choose an HTTP client given a specific request. * - * @param RequestInterface $request - * * @return HttpClient|HttpAsyncClient */ private function chooseHttpClient(RequestInterface $request) diff --git a/src/HttpMethodsClient.php b/src/HttpMethodsClient.php index 0ec1e14..a1ef2c8 100644 --- a/src/HttpMethodsClient.php +++ b/src/HttpMethodsClient.php @@ -50,7 +50,6 @@ public function __construct(HttpClient $httpClient, RequestFactory $requestFacto * Sends a GET request. * * @param string|UriInterface $uri - * @param array $headers * * @throws Exception * @@ -65,7 +64,6 @@ public function get($uri, array $headers = []) * Sends an HEAD request. * * @param string|UriInterface $uri - * @param array $headers * * @throws Exception * @@ -80,7 +78,6 @@ public function head($uri, array $headers = []) * Sends a TRACE request. * * @param string|UriInterface $uri - * @param array $headers * * @throws Exception * @@ -95,7 +92,6 @@ public function trace($uri, array $headers = []) * Sends a POST request. * * @param string|UriInterface $uri - * @param array $headers * @param string|StreamInterface|null $body * * @throws Exception @@ -111,7 +107,6 @@ public function post($uri, array $headers = [], $body = null) * Sends a PUT request. * * @param string|UriInterface $uri - * @param array $headers * @param string|StreamInterface|null $body * * @throws Exception @@ -127,7 +122,6 @@ public function put($uri, array $headers = [], $body = null) * Sends a PATCH request. * * @param string|UriInterface $uri - * @param array $headers * @param string|StreamInterface|null $body * * @throws Exception @@ -143,7 +137,6 @@ public function patch($uri, array $headers = [], $body = null) * Sends a DELETE request. * * @param string|UriInterface $uri - * @param array $headers * @param string|StreamInterface|null $body * * @throws Exception @@ -159,7 +152,6 @@ public function delete($uri, array $headers = [], $body = null) * Sends an OPTIONS request. * * @param string|UriInterface $uri - * @param array $headers * @param string|StreamInterface|null $body * * @throws Exception @@ -174,9 +166,8 @@ public function options($uri, array $headers = [], $body = null) /** * Sends a request with any HTTP method. * - * @param string $method HTTP method to use + * @param string $method HTTP method to use * @param string|UriInterface $uri - * @param array $headers * @param string|StreamInterface|null $body * * @throws Exception diff --git a/src/Plugin.php b/src/Plugin.php index 6248fc7..bfb2668 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -22,9 +22,8 @@ interface Plugin * * @see http://docs.php-http.org/en/latest/plugins/build-your-own.html * - * @param RequestInterface $request - * @param callable $next Next middleware in the chain, the request is passed as the first argument - * @param callable $first First middleware in the chain, used to to restart a request + * @param callable $next Next middleware in the chain, the request is passed as the first argument + * @param callable $first First middleware in the chain, used to to restart a request * * @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception (The same as HttpAsyncClient) */ diff --git a/src/Plugin/AddHostPlugin.php b/src/Plugin/AddHostPlugin.php index 29ab8ae..050feb1 100644 --- a/src/Plugin/AddHostPlugin.php +++ b/src/Plugin/AddHostPlugin.php @@ -25,8 +25,7 @@ final class AddHostPlugin implements Plugin private $replace; /** - * @param UriInterface $host - * @param array $config { + * @param array $config { * * @var bool $replace True will replace all hosts, false will only add host when none is specified. * } @@ -64,9 +63,6 @@ public function handleRequest(RequestInterface $request, callable $next, callabl return $next($request); } - /** - * @param OptionsResolver $resolver - */ private function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ diff --git a/src/Plugin/AddPathPlugin.php b/src/Plugin/AddPathPlugin.php index 93ded1c..1675088 100644 --- a/src/Plugin/AddPathPlugin.php +++ b/src/Plugin/AddPathPlugin.php @@ -25,9 +25,6 @@ final class AddPathPlugin implements Plugin */ private $alteredRequests = []; - /** - * @param UriInterface $uri - */ public function __construct(UriInterface $uri) { if ('' === $uri->getPath()) { diff --git a/src/Plugin/AuthenticationPlugin.php b/src/Plugin/AuthenticationPlugin.php index 194712f..ff33f9b 100644 --- a/src/Plugin/AuthenticationPlugin.php +++ b/src/Plugin/AuthenticationPlugin.php @@ -18,9 +18,6 @@ final class AuthenticationPlugin implements Plugin */ private $authentication; - /** - * @param Authentication $authentication - */ public function __construct(Authentication $authentication) { $this->authentication = $authentication; diff --git a/src/Plugin/CookiePlugin.php b/src/Plugin/CookiePlugin.php index 523628f..3ab5388 100644 --- a/src/Plugin/CookiePlugin.php +++ b/src/Plugin/CookiePlugin.php @@ -25,9 +25,6 @@ final class CookiePlugin implements Plugin */ private $cookieJar; - /** - * @param CookieJar $cookieJar - */ public function __construct(CookieJar $cookieJar) { $this->cookieJar = $cookieJar; @@ -91,7 +88,6 @@ public function handleRequest(RequestInterface $request, callable $next, callabl /** * Creates a cookie from a string. * - * @param RequestInterface $request * @param $setCookie * * @return Cookie|null diff --git a/src/Plugin/DecoderPlugin.php b/src/Plugin/DecoderPlugin.php index 0239d40..3a28f5b 100644 --- a/src/Plugin/DecoderPlugin.php +++ b/src/Plugin/DecoderPlugin.php @@ -120,8 +120,7 @@ private function decodeOnEncodingHeader($headerName, ResponseInterface $response /** * Decorate a stream given an encoding. * - * @param string $encoding - * @param StreamInterface $stream + * @param string $encoding * * @return StreamInterface|false A new stream interface or false if encoding is not supported */ diff --git a/src/Plugin/HistoryPlugin.php b/src/Plugin/HistoryPlugin.php index 5abddbd..0c59a2a 100644 --- a/src/Plugin/HistoryPlugin.php +++ b/src/Plugin/HistoryPlugin.php @@ -21,9 +21,6 @@ final class HistoryPlugin implements Plugin */ private $journal; - /** - * @param Journal $journal - */ public function __construct(Journal $journal) { $this->journal = $journal; diff --git a/src/Plugin/RequestMatcherPlugin.php b/src/Plugin/RequestMatcherPlugin.php index 5f72b02..dd97b3c 100644 --- a/src/Plugin/RequestMatcherPlugin.php +++ b/src/Plugin/RequestMatcherPlugin.php @@ -23,10 +23,6 @@ final class RequestMatcherPlugin implements Plugin */ private $delegatedPlugin; - /** - * @param RequestMatcher $requestMatcher - * @param Plugin $delegatedPlugin - */ public function __construct(RequestMatcher $requestMatcher, Plugin $delegatedPlugin) { $this->requestMatcher = $requestMatcher; diff --git a/src/Plugin/RetryPlugin.php b/src/Plugin/RetryPlugin.php index 0a5b4e7..96cfbb2 100644 --- a/src/Plugin/RetryPlugin.php +++ b/src/Plugin/RetryPlugin.php @@ -109,9 +109,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl } /** - * @param RequestInterface $request - * @param Exception $e - * @param int $retries The number of retries we made before. First time this get called it will be 0. + * @param int $retries The number of retries we made before. First time this get called it will be 0. * * @return int */ diff --git a/src/PluginClient.php b/src/PluginClient.php index c3a5641..6881c93 100644 --- a/src/PluginClient.php +++ b/src/PluginClient.php @@ -102,8 +102,6 @@ public function sendAsyncRequest(RequestInterface $request) /** * Configure the plugin client. * - * @param array $options - * * @return array */ private function configure(array $options = []) diff --git a/src/PluginClientFactory.php b/src/PluginClientFactory.php index bd4c08f..a262f80 100644 --- a/src/PluginClientFactory.php +++ b/src/PluginClientFactory.php @@ -26,8 +26,6 @@ final class PluginClientFactory * application execution. * * @internal - * - * @param callable $factory */ public static function setFactory(callable $factory) { From 637d01c4bac54a586ba4a16a507f7b9872aa5137 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Tue, 20 Nov 2018 16:52:59 +0100 Subject: [PATCH 08/28] Migrate to Travis CI job sequence --- .travis.yml | 96 +++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0c9a55f..97908bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,62 +2,64 @@ language: php sudo: false cache: - directories: - - $HOME/.composer/cache/files + directories: + - $HOME/.composer/cache/files env: - global: - - TEST_COMMAND="composer test" + global: + - TEST_COMMAND="composer test" branches: - except: - - /^analysis-.*$/ + except: + - /^analysis-.*$/ + +php: +- 7.0 +- 7.1 +- 7.2 matrix: - fast_finish: true - include: - - php: 7.0 - env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" - - # Test the latest stable release - - php: 7.0 - - php: 7.1 - - php: 7.2 - - php: 7.2 - env: COVERAGE=true TEST_COMMAND="composer test-ci" DEPENDENCIES="leanphp/phpspec-code-coverage" - - # Test LTS versions - - php: 7.1 - env: DEPENDENCIES="dunglas/symfony-lock:^2" - - php: 7.1 - env: DEPENDENCIES="dunglas/symfony-lock:^3" - - php: 7.1 - env: DEPENDENCIES="dunglas/symfony-lock:^4" STABILITY="rc" - - # Latest dev release - - php: 7.1 - env: STABILITY="dev" - - allow_failures: - - php: 7.3 - sudo: required - - env: STABILITY="dev" + fast_finish: true + allow_failures: + - php: 7.3 + - env: + STABILITY: "dev" + +jobs: + include: + - php: 7.0 + env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" + - php: 7.2 + env: COVERAGE=true DEPENDENCIES="leanphp/phpspec-code-coverage" + script: + - composer test-ci + after_success: + - wget https://scrutinizer-ci.com/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover build/coverage.xml --revision=$TRAVIS_COMMIT + # Test LTS versions + - php: 7.1 + env: DEPENDENCIES="dunglas/symfony-lock:^2" + - php: 7.1 + env: DEPENDENCIES="dunglas/symfony-lock:^3" + - php: 7.1 + env: DEPENDENCIES="dunglas/symfony-lock:^4" STABILITY="rc" + + # Latest dev release + - php: 7.3 + sudo: required + - env: STABILITY="dev" before_install: - - if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi - - if ! [ -z "$STABILITY" ]; then composer config minimum-stability ${STABILITY}; fi; - - if ! [ -z "$DEPENDENCIES" ]; then composer require --no-update ${DEPENDENCIES}; fi; +- if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi +- if ! [ -z "$STABILITY" ]; then composer config minimum-stability ${STABILITY}; fi; +- if ! [ -z "$DEPENDENCIES" ]; then composer require --no-update ${DEPENDENCIES}; fi; install: - - cat composer.json - # To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355 - - if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then composer update --prefer-dist --no-interaction --prefer-stable --quiet; fi - - composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction +- cat composer.json +# To be removed when this issue will be resolved: https://github.com/composer/composer/issues/5355 +- if [[ "$COMPOSER_FLAGS" == *"--prefer-lowest"* ]]; then composer update --prefer-dist --no-interaction --prefer-stable --quiet; fi +- composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction script: - - composer validate --strict --no-check-lock - - $TEST_COMMAND - -after_success: - - if [[ $COVERAGE = true ]]; then wget https://scrutinizer-ci.com/ocular.phar; fi - - if [[ $COVERAGE = true ]]; then php ocular.phar code-coverage:upload --format=php-clover build/coverage.xml; fi +- composer validate --strict --no-check-lock +- composer test From ce5a98c779c218c26c3afe9aa34729ac50ccac99 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Tue, 20 Nov 2018 17:01:01 +0100 Subject: [PATCH 09/28] Remove CS-fixer under 7.3 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 97908bf..796c813 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,8 +22,6 @@ matrix: fast_finish: true allow_failures: - php: 7.3 - - env: - STABILITY: "dev" jobs: include: @@ -47,6 +45,8 @@ jobs: # Latest dev release - php: 7.3 sudo: required + before_install: + - composer remove --dev friendsofphp/php-cs-fixer - env: STABILITY="dev" before_install: From 1cf0f9efb77e943d9af75095c9ebd34d37acbd47 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Tue, 20 Nov 2018 17:36:31 +0100 Subject: [PATCH 10/28] Remove StyleCI config --- .styleci.yml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .styleci.yml diff --git a/.styleci.yml b/.styleci.yml deleted file mode 100644 index 5328b61..0000000 --- a/.styleci.yml +++ /dev/null @@ -1,14 +0,0 @@ -preset: symfony - -finder: - exclude: - - "spec" - path: - - "src" - - "tests" - -enabled: - - short_array_syntax - -disabled: - - phpdoc_annotation_without_dot # This is still buggy: https://github.com/symfony/symfony/pull/19198 From 543b2a2d8bee5499231cc48c5e081337e6c90e6f Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Thu, 22 Nov 2018 10:27:30 +0100 Subject: [PATCH 11/28] [2.0] Add types (#117) * Add types where possible * Add spec to autoload-dev * Fix signatures * Use ::class anywhere * Add `: Promise` return type to Plugin::handleRequest --- CHANGELOG.md | 4 ++ composer.json | 5 ++ spec/BatchClientSpec.php | 12 ++-- spec/BatchResultSpec.php | 7 +- spec/EmulatedHttpAsyncClientSpec.php | 17 +++-- spec/EmulatedHttpClientSpec.php | 11 +-- spec/Exception/BatchExceptionSpec.php | 10 +-- spec/FlexibleHttpClientSpec.php | 15 ++-- .../LeastUsedClientPoolSpec.php | 25 ++++--- spec/HttpClientPool/RandomClientPoolSpec.php | 25 ++++--- .../RoundRobinClientPoolSpec.php | 25 ++++--- spec/HttpClientPoolItemSpec.php | 15 ++-- spec/HttpClientRouterSpec.php | 12 ++-- spec/HttpMethodsClientSpec.php | 61 ++++++++++------ spec/Plugin/AddHostPluginSpec.php | 12 ++-- spec/Plugin/AddPathPluginSpec.php | 12 ++-- spec/Plugin/AuthenticationPluginSpec.php | 6 +- spec/Plugin/BaseUriPluginSpec.php | 12 ++-- spec/Plugin/ContentLengthPluginSpec.php | 10 +-- spec/Plugin/ContentTypePluginSpec.php | 24 ++++--- spec/Plugin/CookiePluginSpec.php | 71 +++++-------------- spec/Plugin/DecoderPluginSpec.php | 12 ++-- spec/Plugin/ErrorPluginSpec.php | 21 +++--- spec/Plugin/HeaderAppendPluginSpec.php | 10 +-- spec/Plugin/HeaderDefaultsPluginSpec.php | 10 +-- spec/Plugin/HeaderRemovePluginSpec.php | 10 +-- spec/Plugin/HeaderSetPluginSpec.php | 10 +-- spec/Plugin/HistoryPluginSpec.php | 3 +- spec/Plugin/PluginStub.php | 25 +++++++ spec/Plugin/QueryDefaultsPluginSpec.php | 14 ++-- spec/Plugin/RedirectPluginSpec.php | 45 ++++++------ spec/Plugin/RequestMatcherPluginSpec.php | 7 +- spec/Plugin/RetryPluginSpec.php | 16 +++-- spec/PluginClientFactorySpec.php | 6 +- spec/PluginClientSpec.php | 14 ++-- src/BatchClient.php | 2 +- src/BatchResult.php | 30 +++----- src/Deferred.php | 4 +- src/HttpClientPool.php | 2 +- src/HttpClientPool/LeastUsedClientPool.php | 2 +- src/HttpClientPool/RandomClientPool.php | 2 +- src/HttpClientPool/RoundRobinClientPool.php | 3 +- src/HttpMethodsClient.php | 36 +++------- src/Plugin.php | 2 +- src/Plugin/AddHostPlugin.php | 3 +- src/Plugin/AddPathPlugin.php | 3 +- src/Plugin/AuthenticationPlugin.php | 3 +- src/Plugin/BaseUriPlugin.php | 3 +- src/Plugin/ContentLengthPlugin.php | 3 +- src/Plugin/ContentTypePlugin.php | 7 +- src/Plugin/CookiePlugin.php | 5 +- src/Plugin/DecoderPlugin.php | 3 +- src/Plugin/ErrorPlugin.php | 5 +- src/Plugin/HeaderAppendPlugin.php | 5 +- src/Plugin/HeaderDefaultsPlugin.php | 3 +- src/Plugin/HeaderRemovePlugin.php | 3 +- src/Plugin/HeaderSetPlugin.php | 5 +- src/Plugin/HistoryPlugin.php | 3 +- src/Plugin/QueryDefaultsPlugin.php | 3 +- src/Plugin/RedirectPlugin.php | 7 +- src/Plugin/RequestMatcherPlugin.php | 3 +- src/Plugin/RetryPlugin.php | 3 +- src/PluginClient.php | 8 +-- src/PluginClientFactory.php | 4 +- 64 files changed, 415 insertions(+), 344 deletions(-) create mode 100644 spec/Plugin/PluginStub.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c268e8..c6a01d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 2.0 (unreleased) +### Changed +- Abstract method `HttpClientPool::chooseHttpClient()` has now an explicit return type (`Http\Client\Common\HttpClientPoolItem`) +- Interface method `Plugin::handleRequest(...)` has now an explicit return type (`Http\Promise\Promise`) + ### Removed - Deprecated option `debug_plugins` has been removed from `PluginClient` diff --git a/composer.json b/composer.json index 882758b..0b32bc2 100644 --- a/composer.json +++ b/composer.json @@ -35,6 +35,11 @@ "Http\\Client\\Common\\": "src/" } }, + "autoload-dev": { + "psr-4": { + "spec\\Http\\Client\\Common\\": "spec/" + } + }, "scripts": { "cs-check": "vendor/bin/php-cs-fixer fix --dry-run", "cs-fix": "vendor/bin/php-cs-fixer fix", diff --git a/spec/BatchClientSpec.php b/spec/BatchClientSpec.php index 8b7e96d..86c6c8b 100644 --- a/spec/BatchClientSpec.php +++ b/spec/BatchClientSpec.php @@ -6,12 +6,16 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; +use Http\Client\Common\BatchClient; +use Http\Client\Common\BatchResult; +use Http\Client\Exception\HttpException; +use Http\Client\Common\Exception\BatchException; class BatchClientSpec extends ObjectBehavior { public function let(HttpClient $client) { - $this->beAnInstanceOf('Http\Client\Common\BatchClient', [$client]); + $this->beAnInstanceOf(BatchClient::class, [$client]); } public function it_send_multiple_request_using_send_request(HttpClient $client, RequestInterface $request1, RequestInterface $request2, ResponseInterface $response1, ResponseInterface $response2) @@ -19,14 +23,14 @@ public function it_send_multiple_request_using_send_request(HttpClient $client, $client->sendRequest($request1)->willReturn($response1); $client->sendRequest($request2)->willReturn($response2); - $this->sendRequests([$request1, $request2])->shouldReturnAnInstanceOf('Http\Client\Common\BatchResult'); + $this->sendRequests([$request1, $request2])->shouldReturnAnInstanceOf(BatchResult::class); } public function it_throw_batch_exception_if_one_or_more_request_failed(HttpClient $client, RequestInterface $request1, RequestInterface $request2, ResponseInterface $response) { $client->sendRequest($request1)->willReturn($response); - $client->sendRequest($request2)->willThrow('Http\Client\Exception\HttpException'); + $client->sendRequest($request2)->willThrow(HttpException::class); - $this->shouldThrow('Http\Client\Common\Exception\BatchException')->duringSendRequests([$request1, $request2]); + $this->shouldThrow(BatchException::class)->duringSendRequests([$request1, $request2]); } } diff --git a/spec/BatchResultSpec.php b/spec/BatchResultSpec.php index aa3bb14..90a80a5 100644 --- a/spec/BatchResultSpec.php +++ b/spec/BatchResultSpec.php @@ -6,12 +6,13 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; +use Http\Client\Common\BatchResult; class BatchResultSpec extends ObjectBehavior { public function it_is_initializable() { - $this->beAnInstanceOf('Http\Client\Common\BatchResult'); + $this->beAnInstanceOf(BatchResult::class); } public function it_is_immutable(RequestInterface $request, ResponseInterface $response) @@ -19,7 +20,7 @@ public function it_is_immutable(RequestInterface $request, ResponseInterface $re $new = $this->addResponse($request, $response); $this->getResponses()->shouldReturn([]); - $new->shouldHaveType('Http\Client\Common\BatchResult'); + $new->shouldHaveType(BatchResult::class); $new->getResponses()->shouldReturn([$response]); } @@ -37,7 +38,7 @@ public function it_has_a_response_for_a_request(RequestInterface $request, Respo { $new = $this->addResponse($request, $response); - $this->shouldThrow('UnexpectedValueException')->duringGetResponseFor($request); + $this->shouldThrow(\UnexpectedValueException::class)->duringGetResponseFor($request); $this->isSuccessful($request)->shouldReturn(false); $new->getResponseFor($request)->shouldReturn($response); $new->isSuccessful($request)->shouldReturn(true); diff --git a/spec/EmulatedHttpAsyncClientSpec.php b/spec/EmulatedHttpAsyncClientSpec.php index ca8a4d1..226008b 100644 --- a/spec/EmulatedHttpAsyncClientSpec.php +++ b/spec/EmulatedHttpAsyncClientSpec.php @@ -6,6 +6,11 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; +use Http\Client\Common\EmulatedHttpAsyncClient; +use Http\Client\HttpAsyncClient; +use Http\Client\Promise\HttpFulfilledPromise; +use Http\Client\Exception\TransferException; +use Http\Client\Promise\HttpRejectedPromise; class EmulatedHttpAsyncClientSpec extends ObjectBehavior { @@ -16,17 +21,17 @@ public function let(HttpClient $httpClient) public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\EmulatedHttpAsyncClient'); + $this->shouldHaveType(EmulatedHttpAsyncClient::class); } public function it_is_an_http_client() { - $this->shouldImplement('Http\Client\HttpClient'); + $this->shouldImplement(HttpClient::class); } public function it_is_an_async_http_client() { - $this->shouldImplement('Http\Client\HttpAsyncClient'); + $this->shouldImplement(HttpAsyncClient::class); } public function it_emulates_a_successful_request( @@ -36,14 +41,14 @@ public function it_emulates_a_successful_request( ) { $httpClient->sendRequest($request)->willReturn($response); - $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); + $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf(HttpFulfilledPromise::class); } public function it_emulates_a_failed_request(HttpClient $httpClient, RequestInterface $request) { - $httpClient->sendRequest($request)->willThrow('Http\Client\Exception\TransferException'); + $httpClient->sendRequest($request)->willThrow(TransferException::class); - $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); + $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf(HttpRejectedPromise::class); } public function it_decorates_the_underlying_client( diff --git a/spec/EmulatedHttpClientSpec.php b/spec/EmulatedHttpClientSpec.php index cf6e076..adf206f 100644 --- a/spec/EmulatedHttpClientSpec.php +++ b/spec/EmulatedHttpClientSpec.php @@ -4,10 +4,13 @@ use Http\Client\Exception\TransferException; use Http\Client\HttpAsyncClient; +use Http\Client\HttpClient; use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; +use Http\Client\Common\EmulatedHttpClient; +use Http\Client\Exception; class EmulatedHttpClientSpec extends ObjectBehavior { @@ -18,17 +21,17 @@ public function let(HttpAsyncClient $httpAsyncClient) public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\EmulatedHttpClient'); + $this->shouldHaveType(EmulatedHttpClient::class); } public function it_is_an_http_client() { - $this->shouldImplement('Http\Client\HttpClient'); + $this->shouldImplement(HttpClient::class); } public function it_is_an_async_http_client() { - $this->shouldImplement('Http\Client\HttpAsyncClient'); + $this->shouldImplement(HttpAsyncClient::class); } public function it_emulates_a_successful_request( @@ -54,7 +57,7 @@ public function it_emulates_a_failed_request(HttpAsyncClient $httpAsyncClient, R $httpAsyncClient->sendAsyncRequest($request)->willReturn($promise); - $this->shouldThrow('Http\Client\Exception')->duringSendRequest($request); + $this->shouldThrow(Exception::class)->duringSendRequest($request); } public function it_decorates_the_underlying_client( diff --git a/spec/Exception/BatchExceptionSpec.php b/spec/Exception/BatchExceptionSpec.php index 0a32607..0205843 100644 --- a/spec/Exception/BatchExceptionSpec.php +++ b/spec/Exception/BatchExceptionSpec.php @@ -3,7 +3,9 @@ namespace spec\Http\Client\Common\Exception; use Http\Client\Common\BatchResult; +use Http\Client\Exception; use PhpSpec\ObjectBehavior; +use Http\Client\Common\Exception\BatchException; class BatchExceptionSpec extends ObjectBehavior { @@ -15,21 +17,21 @@ public function let() public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\Exception\BatchException'); + $this->shouldHaveType(BatchException::class); } public function it_is_a_runtime_exception() { - $this->shouldHaveType('RuntimeException'); + $this->shouldHaveType(\RuntimeException::class); } public function it_is_an_exception() { - $this->shouldImplement('Http\Client\Exception'); + $this->shouldImplement(Exception::class); } public function it_has_a_batch_result() { - $this->getResult()->shouldHaveType('Http\Client\Common\BatchResult'); + $this->getResult()->shouldHaveType(BatchResult::class); } } diff --git a/spec/FlexibleHttpClientSpec.php b/spec/FlexibleHttpClientSpec.php index 769b4c3..b63aa3d 100644 --- a/spec/FlexibleHttpClientSpec.php +++ b/spec/FlexibleHttpClientSpec.php @@ -8,6 +8,7 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; +use Http\Client\Common\FlexibleHttpClient; class FlexibleHttpClientSpec extends ObjectBehavior { @@ -18,24 +19,24 @@ public function let(HttpClient $httpClient) public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\FlexibleHttpClient'); + $this->shouldHaveType(FlexibleHttpClient::class); } public function it_is_an_http_client() { - $this->shouldImplement('Http\Client\HttpClient'); + $this->shouldImplement(HttpClient::class); } public function it_is_an_async_http_client() { - $this->shouldImplement('Http\Client\HttpAsyncClient'); + $this->shouldImplement(HttpAsyncClient::class); } public function it_throw_exception_if_invalid_client() { $this->beConstructedWith(null); - $this->shouldThrow('\LogicException')->duringInstantiation(); + $this->shouldThrow(\LogicException::class)->duringInstantiation(); } public function it_emulates_an_async_client( @@ -53,7 +54,7 @@ public function it_emulates_an_async_client( $this->sendRequest($syncRequest)->shouldReturn($syncResponse); $promise = $this->sendAsyncRequest($asyncRequest); - $promise->shouldHaveType('Http\Promise\Promise'); + $promise->shouldHaveType(Promise::class); $promise->wait()->shouldReturn($asyncResponse); } @@ -77,8 +78,8 @@ public function it_emulates_a_client( public function it_does_not_emulate_a_client($client, RequestInterface $syncRequest, RequestInterface $asyncRequest) { - $client->implement('Http\Client\HttpClient'); - $client->implement('Http\Client\HttpAsyncClient'); + $client->implement(HttpClient::class); + $client->implement(HttpAsyncClient::class); $client->sendRequest($syncRequest)->shouldBeCalled(); $client->sendRequest($asyncRequest)->shouldNotBeCalled(); diff --git a/spec/HttpClientPool/LeastUsedClientPoolSpec.php b/spec/HttpClientPool/LeastUsedClientPoolSpec.php index 8642c31..9c02e47 100644 --- a/spec/HttpClientPool/LeastUsedClientPoolSpec.php +++ b/spec/HttpClientPool/LeastUsedClientPoolSpec.php @@ -10,28 +10,31 @@ use Prophecy\Argument; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Http\Client\Common\HttpClientPool\LeastUsedClientPool; +use Http\Client\Common\Exception\HttpClientNotFoundException; +use Http\Client\Exception\HttpException; class LeastUsedClientPoolSpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\HttpClientPool\LeastUsedClientPool'); + $this->shouldHaveType(LeastUsedClientPool::class); } public function it_is_an_http_client() { - $this->shouldImplement('Http\Client\HttpClient'); + $this->shouldImplement(HttpClient::class); } public function it_is_an_async_http_client() { - $this->shouldImplement('Http\Client\HttpAsyncClient'); + $this->shouldImplement(HttpAsyncClient::class); } public function it_throw_exception_with_no_client(RequestInterface $request) { - $this->shouldThrow('Http\Client\Common\Exception\HttpClientNotFoundException')->duringSendRequest($request); - $this->shouldThrow('Http\Client\Common\Exception\HttpClientNotFoundException')->duringSendAsyncRequest($request); + $this->shouldThrow(HttpClientNotFoundException::class)->duringSendRequest($request); + $this->shouldThrow(HttpClientNotFoundException::class)->duringSendAsyncRequest($request); } public function it_sends_request(HttpClient $httpClient, RequestInterface $request, ResponseInterface $response) @@ -54,19 +57,19 @@ public function it_sends_async_request(HttpAsyncClient $httpAsyncClient, Request public function it_throw_exception_if_no_more_enable_client(HttpClient $client, RequestInterface $request) { $this->addHttpClient($client); - $client->sendRequest($request)->willThrow('Http\Client\Exception\HttpException'); + $client->sendRequest($request)->willThrow(HttpException::class); - $this->shouldThrow('Http\Client\Exception\HttpException')->duringSendRequest($request); - $this->shouldThrow('Http\Client\Common\Exception\HttpClientNotFoundException')->duringSendRequest($request); + $this->shouldThrow(HttpException::class)->duringSendRequest($request); + $this->shouldThrow(HttpClientNotFoundException::class)->duringSendRequest($request); } public function it_reenable_client(HttpClient $client, RequestInterface $request) { $this->addHttpClient(new HttpClientPoolItem($client->getWrappedObject(), 0)); - $client->sendRequest($request)->willThrow('Http\Client\Exception\HttpException'); + $client->sendRequest($request)->willThrow(HttpException::class); - $this->shouldThrow('Http\Client\Exception\HttpException')->duringSendRequest($request); - $this->shouldThrow('Http\Client\Exception\HttpException')->duringSendRequest($request); + $this->shouldThrow(HttpException::class)->duringSendRequest($request); + $this->shouldThrow(HttpException::class)->duringSendRequest($request); } public function it_uses_the_lowest_request_client(HttpClientPoolItem $client1, HttpClientPoolItem $client2, RequestInterface $request, ResponseInterface $response) diff --git a/spec/HttpClientPool/RandomClientPoolSpec.php b/spec/HttpClientPool/RandomClientPoolSpec.php index 4054d82..fb0e5ad 100644 --- a/spec/HttpClientPool/RandomClientPoolSpec.php +++ b/spec/HttpClientPool/RandomClientPoolSpec.php @@ -10,28 +10,31 @@ use Prophecy\Argument; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Http\Client\Common\HttpClientPool\RandomClientPool; +use Http\Client\Common\Exception\HttpClientNotFoundException; +use Http\Client\Exception\HttpException; class RandomClientPoolSpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\HttpClientPool\RandomClientPool'); + $this->shouldHaveType(RandomClientPool::class); } public function it_is_an_http_client() { - $this->shouldImplement('Http\Client\HttpClient'); + $this->shouldImplement(HttpClient::class); } public function it_is_an_async_http_client() { - $this->shouldImplement('Http\Client\HttpAsyncClient'); + $this->shouldImplement(HttpAsyncClient::class); } public function it_throw_exception_with_no_client(RequestInterface $request) { - $this->shouldThrow('Http\Client\Common\Exception\HttpClientNotFoundException')->duringSendRequest($request); - $this->shouldThrow('Http\Client\Common\Exception\HttpClientNotFoundException')->duringSendAsyncRequest($request); + $this->shouldThrow(HttpClientNotFoundException::class)->duringSendRequest($request); + $this->shouldThrow(HttpClientNotFoundException::class)->duringSendAsyncRequest($request); } public function it_sends_request(HttpClient $httpClient, RequestInterface $request, ResponseInterface $response) @@ -54,18 +57,18 @@ public function it_sends_async_request(HttpAsyncClient $httpAsyncClient, Request public function it_throw_exception_if_no_more_enable_client(HttpClient $client, RequestInterface $request) { $this->addHttpClient($client); - $client->sendRequest($request)->willThrow('Http\Client\Exception\HttpException'); + $client->sendRequest($request)->willThrow(HttpException::class); - $this->shouldThrow('Http\Client\Exception\HttpException')->duringSendRequest($request); - $this->shouldThrow('Http\Client\Common\Exception\HttpClientNotFoundException')->duringSendRequest($request); + $this->shouldThrow(HttpException::class)->duringSendRequest($request); + $this->shouldThrow(HttpClientNotFoundException::class)->duringSendRequest($request); } public function it_reenable_client(HttpClient $client, RequestInterface $request) { $this->addHttpClient(new HttpClientPoolItem($client->getWrappedObject(), 0)); - $client->sendRequest($request)->willThrow('Http\Client\Exception\HttpException'); + $client->sendRequest($request)->willThrow(HttpException::class); - $this->shouldThrow('Http\Client\Exception\HttpException')->duringSendRequest($request); - $this->shouldThrow('Http\Client\Exception\HttpException')->duringSendRequest($request); + $this->shouldThrow(HttpException::class)->duringSendRequest($request); + $this->shouldThrow(HttpException::class)->duringSendRequest($request); } } diff --git a/spec/HttpClientPool/RoundRobinClientPoolSpec.php b/spec/HttpClientPool/RoundRobinClientPoolSpec.php index 48c2d01..925f548 100644 --- a/spec/HttpClientPool/RoundRobinClientPoolSpec.php +++ b/spec/HttpClientPool/RoundRobinClientPoolSpec.php @@ -10,28 +10,31 @@ use Prophecy\Argument; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Http\Client\Common\HttpClientPool\RoundRobinClientPool; +use Http\Client\Common\Exception\HttpClientNotFoundException; +use Http\Client\Exception\HttpException; class RoundRobinClientPoolSpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\HttpClientPool\RoundRobinClientPool'); + $this->shouldHaveType(RoundRobinClientPool::class); } public function it_is_an_http_client() { - $this->shouldImplement('Http\Client\HttpClient'); + $this->shouldImplement(HttpClient::class); } public function it_is_an_async_http_client() { - $this->shouldImplement('Http\Client\HttpAsyncClient'); + $this->shouldImplement(HttpAsyncClient::class); } public function it_throw_exception_with_no_client(RequestInterface $request) { - $this->shouldThrow('Http\Client\Common\Exception\HttpClientNotFoundException')->duringSendRequest($request); - $this->shouldThrow('Http\Client\Common\Exception\HttpClientNotFoundException')->duringSendAsyncRequest($request); + $this->shouldThrow(HttpClientNotFoundException::class)->duringSendRequest($request); + $this->shouldThrow(HttpClientNotFoundException::class)->duringSendAsyncRequest($request); } public function it_sends_request(HttpClient $httpClient, RequestInterface $request, ResponseInterface $response) @@ -54,19 +57,19 @@ public function it_sends_async_request(HttpAsyncClient $httpAsyncClient, Request public function it_throw_exception_if_no_more_enable_client(HttpClient $client, RequestInterface $request) { $this->addHttpClient($client); - $client->sendRequest($request)->willThrow('Http\Client\Exception\HttpException'); + $client->sendRequest($request)->willThrow(HttpException::class); - $this->shouldThrow('Http\Client\Exception\HttpException')->duringSendRequest($request); - $this->shouldThrow('Http\Client\Common\Exception\HttpClientNotFoundException')->duringSendRequest($request); + $this->shouldThrow(HttpException::class)->duringSendRequest($request); + $this->shouldThrow(HttpClientNotFoundException::class)->duringSendRequest($request); } public function it_reenable_client(HttpClient $client, RequestInterface $request) { $this->addHttpClient(new HttpClientPoolItem($client->getWrappedObject(), 0)); - $client->sendRequest($request)->willThrow('Http\Client\Exception\HttpException'); + $client->sendRequest($request)->willThrow(HttpException::class); - $this->shouldThrow('Http\Client\Exception\HttpException')->duringSendRequest($request); - $this->shouldThrow('Http\Client\Exception\HttpException')->duringSendRequest($request); + $this->shouldThrow(HttpException::class)->duringSendRequest($request); + $this->shouldThrow(HttpException::class)->duringSendRequest($request); } public function it_round_between_clients(HttpClient $client1, HttpClient $client2, RequestInterface $request, ResponseInterface $response) diff --git a/spec/HttpClientPoolItemSpec.php b/spec/HttpClientPoolItemSpec.php index cba68d8..f44351b 100644 --- a/spec/HttpClientPoolItemSpec.php +++ b/spec/HttpClientPoolItemSpec.php @@ -12,6 +12,7 @@ use Prophecy\Argument; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; +use Http\Client\Exception\RequestException; class HttpClientPoolItemSpec extends ObjectBehavior { @@ -22,12 +23,12 @@ public function let(HttpClient $httpClient) public function it_is_an_http_client() { - $this->shouldImplement('Http\Client\HttpClient'); + $this->shouldImplement(HttpClient::class); } public function it_is_an_async_http_client() { - $this->shouldImplement('Http\Client\HttpAsyncClient'); + $this->shouldImplement(HttpAsyncClient::class); } public function it_sends_request(HttpClient $httpClient, RequestInterface $request, ResponseInterface $response) @@ -53,7 +54,7 @@ public function it_disable_himself_on_send_request(HttpClient $httpClient, Reque $httpClient->sendRequest($request)->willThrow($exception); $this->shouldThrow($exception)->duringSendRequest($request); $this->isDisabled()->shouldReturn(true); - $this->shouldThrow('Http\Client\Exception\RequestException')->duringSendRequest($request); + $this->shouldThrow(RequestException::class)->duringSendRequest($request); } public function it_disable_himself_on_send_async_request(HttpAsyncClient $httpAsyncClient, RequestInterface $request) @@ -63,9 +64,9 @@ public function it_disable_himself_on_send_async_request(HttpAsyncClient $httpAs $promise = new HttpRejectedPromise(new TransferException()); $httpAsyncClient->sendAsyncRequest($request)->willReturn($promise); - $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); + $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf(HttpRejectedPromise::class); $this->isDisabled()->shouldReturn(true); - $this->shouldThrow('Http\Client\Exception\RequestException')->duringSendAsyncRequest($request); + $this->shouldThrow(RequestException::class)->duringSendAsyncRequest($request); } public function it_reactivate_himself_on_send_request(HttpClient $httpClient, RequestInterface $request) @@ -87,9 +88,9 @@ public function it_reactivate_himself_on_send_async_request(HttpAsyncClient $htt $promise = new HttpRejectedPromise(new TransferException()); $httpAsyncClient->sendAsyncRequest($request)->willReturn($promise); - $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); + $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf(HttpRejectedPromise::class); $this->isDisabled()->shouldReturn(false); - $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); + $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf(HttpRejectedPromise::class); } public function it_increments_request_count(HttpAsyncClient $httpAsyncClient, RequestInterface $request, ResponseInterface $response) diff --git a/spec/HttpClientRouterSpec.php b/spec/HttpClientRouterSpec.php index e43acea..68446a4 100644 --- a/spec/HttpClientRouterSpec.php +++ b/spec/HttpClientRouterSpec.php @@ -9,22 +9,24 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; +use Http\Client\Common\HttpClientRouter; +use Http\Client\Exception\RequestException; class HttpClientRouterSpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\HttpClientRouter'); + $this->shouldHaveType(HttpClientRouter::class); } public function it_is_an_http_client() { - $this->shouldImplement('Http\Client\HttpClient'); + $this->shouldImplement(HttpClient::class); } public function it_is_an_async_http_client() { - $this->shouldImplement('Http\Client\HttpAsyncClient'); + $this->shouldImplement(HttpAsyncClient::class); } public function it_send_request(RequestMatcher $matcher, HttpClient $client, RequestInterface $request, ResponseInterface $response) @@ -50,7 +52,7 @@ public function it_throw_exception_on_send_request(RequestMatcher $matcher, Http $this->addClient($client, $matcher); $matcher->matches($request)->willReturn(false); - $this->shouldThrow('Http\Client\Exception\RequestException')->duringSendRequest($request); + $this->shouldThrow(RequestException::class)->duringSendRequest($request); } public function it_throw_exception_on_send_async_request(RequestMatcher $matcher, HttpAsyncClient $client, RequestInterface $request) @@ -58,6 +60,6 @@ public function it_throw_exception_on_send_async_request(RequestMatcher $matcher $this->addClient($client, $matcher); $matcher->matches($request)->willReturn(false); - $this->shouldThrow('Http\Client\Exception\RequestException')->duringSendAsyncRequest($request); + $this->shouldThrow(RequestException::class)->duringSendAsyncRequest($request); } } diff --git a/spec/HttpMethodsClientSpec.php b/spec/HttpMethodsClientSpec.php index b68c8c4..74e0810 100644 --- a/spec/HttpMethodsClientSpec.php +++ b/spec/HttpMethodsClientSpec.php @@ -2,19 +2,20 @@ namespace spec\Http\Client\Common; -use Http\Client\HttpClient; +use GuzzleHttp\Psr7\Response; use Http\Client\Common\HttpMethodsClient; +use Http\Client\HttpClient; use Http\Message\MessageFactory; +use PhpSpec\ObjectBehavior; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; -use PhpSpec\ObjectBehavior; class HttpMethodsClientSpec extends ObjectBehavior { public function let(HttpClient $client, MessageFactory $messageFactory) { $this->beAnInstanceOf( - 'spec\Http\Client\Common\HttpMethodsClientStub', [ + HttpMethodsClientStub::class, [ $client, $messageFactory, ] @@ -25,56 +26,56 @@ public function it_sends_a_get_request() { $data = HttpMethodsClientStub::$requestData; - $this->get($data['uri'], $data['headers'])->shouldReturn(true); + $this->get($data['uri'], $data['headers'])->shouldReturnAnInstanceOf(ResponseInterface::class); } public function it_sends_a_head_request() { $data = HttpMethodsClientStub::$requestData; - $this->head($data['uri'], $data['headers'])->shouldReturn(true); + $this->head($data['uri'], $data['headers'])->shouldReturnAnInstanceOf(ResponseInterface::class); } public function it_sends_a_trace_request() { $data = HttpMethodsClientStub::$requestData; - $this->trace($data['uri'], $data['headers'])->shouldReturn(true); + $this->trace($data['uri'], $data['headers'])->shouldReturnAnInstanceOf(ResponseInterface::class); } public function it_sends_a_post_request() { $data = HttpMethodsClientStub::$requestData; - $this->post($data['uri'], $data['headers'], $data['body'])->shouldReturn(true); + $this->post($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); } public function it_sends_a_put_request() { $data = HttpMethodsClientStub::$requestData; - $this->put($data['uri'], $data['headers'], $data['body'])->shouldReturn(true); + $this->put($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); } public function it_sends_a_patch_request() { $data = HttpMethodsClientStub::$requestData; - $this->patch($data['uri'], $data['headers'], $data['body'])->shouldReturn(true); + $this->patch($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); } public function it_sends_a_delete_request() { $data = HttpMethodsClientStub::$requestData; - $this->delete($data['uri'], $data['headers'], $data['body'])->shouldReturn(true); + $this->delete($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); } public function it_sends_a_options_request() { $data = HttpMethodsClientStub::$requestData; - $this->options($data['uri'], $data['headers'], $data['body'])->shouldReturn(true); + $this->options($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); } public function it_sends_request_with_underlying_client(HttpClient $client, MessageFactory $messageFactory, RequestInterface $request, ResponseInterface $response) @@ -99,17 +100,37 @@ class HttpMethodsClientStub extends HttpMethodsClient /** * {@inheritdoc} */ - public function send($method, $uri, array $headers = [], $body = null) + public function send($method, $uri, array $headers = [], $body = null): ResponseInterface { - if (in_array($method, ['GET', 'HEAD', 'TRACE'])) { - return $uri === self::$requestData['uri'] && - $headers === self::$requestData['headers'] && - is_null($body); + if ($uri !== self::$requestData['uri']) { + throw new \InvalidArgumentException('Invalid URI: '.$uri); } - return in_array($method, ['POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']) && - $uri === self::$requestData['uri'] && - $headers === self::$requestData['headers'] && - $body === self::$requestData['body']; + if ($headers !== self::$requestData['headers']) { + throw new \InvalidArgumentException('Invalid headers: '.print_r($headers, true)); + } + + switch ($method) { + case 'GET': + case 'HEAD': + case 'TRACE': + if (null !== $body) { + throw new \InvalidArgumentException('Non-empty body'); + } + + return new Response(); + case 'POST': + case 'PUT': + case 'PATCH': + case 'DELETE': + case 'OPTIONS': + if ($body !== self::$requestData['body']) { + throw new \InvalidArgumentException('Invalid body: '.print_r($body, true)); + } + + return new Response(); + default: + throw new \InvalidArgumentException('Invalid method: '.$method); + } } } diff --git a/spec/Plugin/AddHostPluginSpec.php b/spec/Plugin/AddHostPluginSpec.php index a6630bd..2691f10 100644 --- a/spec/Plugin/AddHostPluginSpec.php +++ b/spec/Plugin/AddHostPluginSpec.php @@ -5,6 +5,8 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; use PhpSpec\ObjectBehavior; +use Http\Client\Common\Plugin\AddHostPlugin; +use Http\Client\Common\Plugin; class AddHostPluginSpec extends ObjectBehavior { @@ -17,14 +19,14 @@ public function it_is_initializable(UriInterface $uri) { $uri->getHost()->shouldBeCalled()->willReturn('example.com'); - $this->shouldHaveType('Http\Client\Common\Plugin\AddHostPlugin'); + $this->shouldHaveType(AddHostPlugin::class); } public function it_is_a_plugin(UriInterface $uri) { $uri->getHost()->shouldBeCalled()->willReturn('example.com'); - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_adds_domain( @@ -45,7 +47,7 @@ public function it_adds_domain( $uri->getHost()->shouldBeCalled()->willReturn(''); $this->beConstructedWith($host); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_replaces_domain( @@ -65,7 +67,7 @@ public function it_replaces_domain( $uri->withPort(8000)->shouldBeCalled()->willReturn($uri); $this->beConstructedWith($host, ['replace' => true]); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_nothing_when_domain_exists( @@ -77,6 +79,6 @@ public function it_does_nothing_when_domain_exists( $uri->getHost()->shouldBeCalled()->willReturn('default.com'); $this->beConstructedWith($host); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } } diff --git a/spec/Plugin/AddPathPluginSpec.php b/spec/Plugin/AddPathPluginSpec.php index c95301c..a76eb16 100644 --- a/spec/Plugin/AddPathPluginSpec.php +++ b/spec/Plugin/AddPathPluginSpec.php @@ -5,6 +5,8 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; use PhpSpec\ObjectBehavior; +use Http\Client\Common\Plugin\AddPathPlugin; +use Http\Client\Common\Plugin; class AddPathPluginSpec extends ObjectBehavior { @@ -17,14 +19,14 @@ public function it_is_initializable(UriInterface $uri) { $uri->getPath()->shouldBeCalled()->willReturn('/api'); - $this->shouldHaveType('Http\Client\Common\Plugin\AddPathPlugin'); + $this->shouldHaveType(AddPathPlugin::class); } public function it_is_a_plugin(UriInterface $uri) { $uri->getPath()->shouldBeCalled()->willReturn('/api'); - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_adds_path( @@ -41,7 +43,7 @@ public function it_adds_path( $uri->getPath()->shouldBeCalled()->willReturn('/users'); $this->beConstructedWith($host); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_throws_exception_on_trailing_slash(UriInterface $host) @@ -49,7 +51,7 @@ public function it_throws_exception_on_trailing_slash(UriInterface $host) $host->getPath()->shouldBeCalled()->willReturn('/api/'); $this->beConstructedWith($host); - $this->shouldThrow('\LogicException')->duringInstantiation(); + $this->shouldThrow(\LogicException::class)->duringInstantiation(); } public function it_throws_exception_on_empty_path(UriInterface $host) @@ -57,6 +59,6 @@ public function it_throws_exception_on_empty_path(UriInterface $host) $host->getPath()->shouldBeCalled()->willReturn(''); $this->beConstructedWith($host); - $this->shouldThrow('\LogicException')->duringInstantiation(); + $this->shouldThrow(\LogicException::class)->duringInstantiation(); } } diff --git a/spec/Plugin/AuthenticationPluginSpec.php b/spec/Plugin/AuthenticationPluginSpec.php index 549b507..c86cb3a 100644 --- a/spec/Plugin/AuthenticationPluginSpec.php +++ b/spec/Plugin/AuthenticationPluginSpec.php @@ -7,6 +7,8 @@ use Psr\Http\Message\RequestInterface; use PhpSpec\ObjectBehavior; use Prophecy\Argument; +use Http\Client\Common\Plugin\AuthenticationPlugin; +use Http\Client\Common\Plugin; class AuthenticationPluginSpec extends ObjectBehavior { @@ -17,12 +19,12 @@ public function let(Authentication $authentication) public function it_is_initializable(Authentication $authentication) { - $this->shouldHaveType('Http\Client\Common\Plugin\AuthenticationPlugin'); + $this->shouldHaveType(AuthenticationPlugin::class); } public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_sends_an_authenticated_request(Authentication $authentication, RequestInterface $notAuthedRequest, RequestInterface $authedRequest, Promise $promise) diff --git a/spec/Plugin/BaseUriPluginSpec.php b/spec/Plugin/BaseUriPluginSpec.php index e2f8c46..92f5074 100644 --- a/spec/Plugin/BaseUriPluginSpec.php +++ b/spec/Plugin/BaseUriPluginSpec.php @@ -5,6 +5,8 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; use PhpSpec\ObjectBehavior; +use Http\Client\Common\Plugin\BaseUriPlugin; +use Http\Client\Common\Plugin; class BaseUriPluginSpec extends ObjectBehavior { @@ -18,7 +20,7 @@ public function it_is_initializable(UriInterface $uri) $uri->getHost()->shouldBeCalled()->willReturn('example.com'); $uri->getPath()->shouldBeCalled()->willReturn('/api'); - $this->shouldHaveType('Http\Client\Common\Plugin\BaseUriPlugin'); + $this->shouldHaveType(BaseUriPlugin::class); } public function it_is_a_plugin(UriInterface $uri) @@ -26,7 +28,7 @@ public function it_is_a_plugin(UriInterface $uri) $uri->getHost()->shouldBeCalled()->willReturn('example.com'); $uri->getPath()->shouldBeCalled()->willReturn('/api'); - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_adds_domain_and_path( @@ -50,7 +52,7 @@ public function it_adds_domain_and_path( $uri->getPath()->shouldBeCalled()->willReturn('/users'); $this->beConstructedWith($host); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_adds_domain( @@ -72,7 +74,7 @@ public function it_adds_domain( $uri->getHost()->shouldBeCalled()->willReturn(''); $this->beConstructedWith($host); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_replaces_domain_and_adds_path( @@ -95,6 +97,6 @@ public function it_replaces_domain_and_adds_path( $uri->getPath()->shouldBeCalled()->willReturn('/users'); $this->beConstructedWith($host, ['replace' => true]); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } } diff --git a/spec/Plugin/ContentLengthPluginSpec.php b/spec/Plugin/ContentLengthPluginSpec.php index 6624f6c..a945924 100644 --- a/spec/Plugin/ContentLengthPluginSpec.php +++ b/spec/Plugin/ContentLengthPluginSpec.php @@ -7,17 +7,19 @@ use Psr\Http\Message\StreamInterface; use PhpSpec\ObjectBehavior; use Prophecy\Argument; +use Http\Client\Common\Plugin\ContentLengthPlugin; +use Http\Client\Common\Plugin; class ContentLengthPluginSpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\Plugin\ContentLengthPlugin'); + $this->shouldHaveType(ContentLengthPlugin::class); } public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_adds_content_length_header(RequestInterface $request, StreamInterface $stream) @@ -27,7 +29,7 @@ public function it_adds_content_length_header(RequestInterface $request, StreamI $stream->getSize()->shouldBeCalled()->willReturn(100); $request->withHeader('Content-Length', '100')->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_streams_chunked_if_no_size(RequestInterface $request, StreamInterface $stream) @@ -43,6 +45,6 @@ public function it_streams_chunked_if_no_size(RequestInterface $request, StreamI $request->withBody(Argument::type('Http\Message\Encoding\ChunkStream'))->shouldBeCalled()->willReturn($request); $request->withAddedHeader('Transfer-Encoding', 'chunked')->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } } diff --git a/spec/Plugin/ContentTypePluginSpec.php b/spec/Plugin/ContentTypePluginSpec.php index d2a6ffa..a27d32a 100644 --- a/spec/Plugin/ContentTypePluginSpec.php +++ b/spec/Plugin/ContentTypePluginSpec.php @@ -2,19 +2,21 @@ namespace spec\Http\Client\Common\Plugin; -use Psr\Http\Message\RequestInterface; +use Http\Client\Common\Plugin; +use Http\Client\Common\Plugin\ContentTypePlugin; use PhpSpec\ObjectBehavior; +use Psr\Http\Message\RequestInterface; class ContentTypePluginSpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\Plugin\ContentTypePlugin'); + $this->shouldHaveType(ContentTypePlugin::class); } public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_adds_json_content_type_header(RequestInterface $request) @@ -23,7 +25,7 @@ public function it_adds_json_content_type_header(RequestInterface $request) $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for(json_encode(['foo' => 'bar']))); $request->withHeader('Content-Type', 'application/json')->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_adds_xml_content_type_header(RequestInterface $request) @@ -32,7 +34,7 @@ public function it_adds_xml_content_type_header(RequestInterface $request) $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for('bar')); $request->withHeader('Content-Type', 'application/xml')->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_set_content_type_header(RequestInterface $request) @@ -41,7 +43,7 @@ public function it_does_not_set_content_type_header(RequestInterface $request) $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for('foo')); $request->withHeader('Content-Type', null)->shouldNotBeCalled(); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_set_content_type_header_if_already_one(RequestInterface $request) @@ -50,7 +52,7 @@ public function it_does_not_set_content_type_header_if_already_one(RequestInterf $request->getBody()->shouldNotBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for('foo')); $request->withHeader('Content-Type', null)->shouldNotBeCalled(); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_set_content_type_header_if_size_0_or_unknown(RequestInterface $request) @@ -59,7 +61,7 @@ public function it_does_not_set_content_type_header_if_size_0_or_unknown(Request $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for()); $request->withHeader('Content-Type', null)->shouldNotBeCalled(); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_adds_xml_content_type_header_if_size_limit_is_not_reached_using_default_value(RequestInterface $request) @@ -72,7 +74,7 @@ public function it_adds_xml_content_type_header_if_size_limit_is_not_reached_usi $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for('bar')); $request->withHeader('Content-Type', 'application/xml')->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_adds_xml_content_type_header_if_size_limit_is_not_reached(RequestInterface $request) @@ -86,7 +88,7 @@ public function it_adds_xml_content_type_header_if_size_limit_is_not_reached(Req $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for('bar')); $request->withHeader('Content-Type', 'application/xml')->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_set_content_type_header_if_size_limit_is_reached(RequestInterface $request) @@ -100,6 +102,6 @@ public function it_does_not_set_content_type_header_if_size_limit_is_reached(Req $request->getBody()->shouldBeCalled()->willReturn(\GuzzleHttp\Psr7\stream_for('bar')); $request->withHeader('Content-Type', null)->shouldNotBeCalled(); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } } diff --git a/spec/Plugin/CookiePluginSpec.php b/spec/Plugin/CookiePluginSpec.php index 1f021b1..7bb188c 100644 --- a/spec/Plugin/CookiePluginSpec.php +++ b/spec/Plugin/CookiePluginSpec.php @@ -10,7 +10,10 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; use PhpSpec\ObjectBehavior; -use Prophecy\Argument; +use Http\Client\Common\Plugin\CookiePlugin; +use Http\Client\Common\Plugin; +use Http\Client\Promise\HttpRejectedPromise; +use Http\Client\Exception\TransferException; class CookiePluginSpec extends ObjectBehavior { @@ -25,12 +28,12 @@ public function let() public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\Plugin\CookiePlugin'); + $this->shouldHaveType(CookiePlugin::class); } public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_loads_cookie(RequestInterface $request, UriInterface $uri, Promise $promise) @@ -44,11 +47,7 @@ public function it_loads_cookie(RequestInterface $request, UriInterface $uri, Pr $request->withAddedHeader('Cookie', 'name=value')->willReturn($request); - $this->handleRequest($request, function (RequestInterface $requestReceived) use ($request, $promise) { - if (Argument::is($requestReceived)->scoreArgument($request->getWrappedObject())) { - return $promise->getWrappedObject(); - } - }, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_combines_multiple_cookies_into_one_header(RequestInterface $request, UriInterface $uri, Promise $promise) @@ -65,11 +64,7 @@ public function it_combines_multiple_cookies_into_one_header(RequestInterface $r $request->withAddedHeader('Cookie', 'name=value; name2=value2')->willReturn($request); - $this->handleRequest($request, function (RequestInterface $requestReceived) use ($request, $promise) { - if (Argument::is($requestReceived)->scoreArgument($request->getWrappedObject())) { - return $promise->getWrappedObject(); - } - }, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_load_cookie_if_expired(RequestInterface $request, UriInterface $uri, Promise $promise) @@ -79,11 +74,7 @@ public function it_does_not_load_cookie_if_expired(RequestInterface $request, Ur $request->withAddedHeader('Cookie', 'name=value')->shouldNotBeCalled(); - $this->handleRequest($request, function (RequestInterface $requestReceived) use ($request, $promise) { - if (Argument::is($requestReceived)->scoreArgument($request->getWrappedObject())) { - return $promise->getWrappedObject(); - } - }, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_load_cookie_if_domain_does_not_match(RequestInterface $request, UriInterface $uri, Promise $promise) @@ -96,11 +87,7 @@ public function it_does_not_load_cookie_if_domain_does_not_match(RequestInterfac $request->withAddedHeader('Cookie', 'name=value')->shouldNotBeCalled(); - $this->handleRequest($request, function (RequestInterface $requestReceived) use ($request, $promise) { - if (Argument::is($requestReceived)->scoreArgument($request->getWrappedObject())) { - return $promise->getWrappedObject(); - } - }, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_load_cookie_on_hackish_domains(RequestInterface $request, UriInterface $uri, Promise $promise) @@ -118,11 +105,7 @@ public function it_does_not_load_cookie_on_hackish_domains(RequestInterface $req $request->withAddedHeader('Cookie', 'name=value')->shouldNotBeCalled(); - $this->handleRequest($request, function (RequestInterface $requestReceived) use ($request, $promise) { - if (Argument::is($requestReceived)->scoreArgument($request->getWrappedObject())) { - return $promise->getWrappedObject(); - } - }, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } } @@ -137,11 +120,7 @@ public function it_loads_cookie_on_subdomains(RequestInterface $request, UriInte $request->withAddedHeader('Cookie', 'name=value')->willReturn($request); - $this->handleRequest($request, function (RequestInterface $requestReceived) use ($request, $promise) { - if (Argument::is($requestReceived)->scoreArgument($request->getWrappedObject())) { - return $promise->getWrappedObject(); - } - }, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_load_cookie_if_path_does_not_match(RequestInterface $request, UriInterface $uri, Promise $promise) @@ -155,11 +134,7 @@ public function it_does_not_load_cookie_if_path_does_not_match(RequestInterface $request->withAddedHeader('Cookie', 'name=value')->shouldNotBeCalled(); - $this->handleRequest($request, function (RequestInterface $requestReceived) use ($request, $promise) { - if (Argument::is($requestReceived)->scoreArgument($request->getWrappedObject())) { - return $promise->getWrappedObject(); - } - }, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_load_cookie_when_cookie_is_secure(RequestInterface $request, UriInterface $uri, Promise $promise) @@ -174,11 +149,7 @@ public function it_does_not_load_cookie_when_cookie_is_secure(RequestInterface $ $request->withAddedHeader('Cookie', 'name=value')->shouldNotBeCalled(); - $this->handleRequest($request, function (RequestInterface $requestReceived) use ($request, $promise) { - if (Argument::is($requestReceived)->scoreArgument($request->getWrappedObject())) { - return $promise->getWrappedObject(); - } - }, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_loads_cookie_when_cookie_is_secure(RequestInterface $request, UriInterface $uri, Promise $promise) @@ -193,11 +164,7 @@ public function it_loads_cookie_when_cookie_is_secure(RequestInterface $request, $request->withAddedHeader('Cookie', 'name=value')->willReturn($request); - $this->handleRequest($request, function (RequestInterface $requestReceived) use ($request, $promise) { - if (Argument::is($requestReceived)->scoreArgument($request->getWrappedObject())) { - return $promise->getWrappedObject(); - } - }, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_saves_cookie(RequestInterface $request, ResponseInterface $response, UriInterface $uri) @@ -216,8 +183,8 @@ public function it_saves_cookie(RequestInterface $request, ResponseInterface $re $uri->getPath()->willReturn('/'); $promise = $this->handleRequest($request, $next, function () {}); - $promise->shouldHaveType('Http\Promise\Promise'); - $promise->wait()->shouldReturnAnInstanceOf('Psr\Http\Message\ResponseInterface'); + $promise->shouldHaveType(Promise::class); + $promise->wait()->shouldReturnAnInstanceOf(ResponseInterface::class); } public function it_throws_exception_on_invalid_expires_date( @@ -239,7 +206,7 @@ public function it_throws_exception_on_invalid_expires_date( $uri->getPath()->willReturn('/'); $promise = $this->handleRequest($request, $next, function () {}); - $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); - $promise->shouldThrow('Http\Client\Exception\TransferException')->duringWait(); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); + $promise->shouldThrow(TransferException::class)->duringWait(); } } diff --git a/spec/Plugin/DecoderPluginSpec.php b/spec/Plugin/DecoderPluginSpec.php index 4de938c..1316a90 100644 --- a/spec/Plugin/DecoderPluginSpec.php +++ b/spec/Plugin/DecoderPluginSpec.php @@ -9,17 +9,21 @@ use PhpSpec\Exception\Example\SkippingException; use PhpSpec\ObjectBehavior; use Prophecy\Argument; +use Http\Client\Common\Plugin\DecoderPlugin; +use Http\Client\Common\Plugin; +use Http\Message\Encoding\GzipDecodeStream; +use Http\Message\Encoding\DecompressStream; class DecoderPluginSpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\Plugin\DecoderPlugin'); + $this->shouldHaveType(DecoderPlugin::class); } public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_decodes(RequestInterface $request, ResponseInterface $response, StreamInterface $stream) @@ -60,7 +64,7 @@ public function it_decodes_gzip(RequestInterface $request, ResponseInterface $re $response->hasHeader('Content-Encoding')->willReturn(true); $response->getHeader('Content-Encoding')->willReturn(['gzip']); $response->getBody()->willReturn($stream); - $response->withBody(Argument::type('Http\Message\Encoding\GzipDecodeStream'))->willReturn($response); + $response->withBody(Argument::type(GzipDecodeStream::class))->willReturn($response); $response->withoutHeader('Content-Encoding')->willReturn($response); $stream->isReadable()->willReturn(true); @@ -82,7 +86,7 @@ public function it_decodes_deflate(RequestInterface $request, ResponseInterface $response->hasHeader('Content-Encoding')->willReturn(true); $response->getHeader('Content-Encoding')->willReturn(['deflate']); $response->getBody()->willReturn($stream); - $response->withBody(Argument::type('Http\Message\Encoding\DecompressStream'))->willReturn($response); + $response->withBody(Argument::type(DecompressStream::class))->willReturn($response); $response->withoutHeader('Content-Encoding')->willReturn($response); $stream->isReadable()->willReturn(true); diff --git a/spec/Plugin/ErrorPluginSpec.php b/spec/Plugin/ErrorPluginSpec.php index 5a9e90a..67e5c7e 100644 --- a/spec/Plugin/ErrorPluginSpec.php +++ b/spec/Plugin/ErrorPluginSpec.php @@ -7,17 +7,22 @@ use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; use Prophecy\Argument; +use Http\Client\Common\Plugin\ErrorPlugin; +use Http\Client\Common\Plugin; +use Http\Client\Promise\HttpRejectedPromise; +use Http\Client\Common\Exception\ClientErrorException; +use Http\Client\Common\Exception\ServerErrorException; class ErrorPluginSpec extends ObjectBehavior { public function it_is_initializable() { - $this->beAnInstanceOf('Http\Client\Common\Plugin\ErrorPlugin'); + $this->beAnInstanceOf(ErrorPlugin::class); } public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_throw_client_error_exception_on_4xx_error(RequestInterface $request, ResponseInterface $response) @@ -32,8 +37,8 @@ public function it_throw_client_error_exception_on_4xx_error(RequestInterface $r }; $promise = $this->handleRequest($request, $next, function () {}); - $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); - $promise->shouldThrow('Http\Client\Common\Exception\ClientErrorException')->duringWait(); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); + $promise->shouldThrow(ClientErrorException::class)->duringWait(); } public function it_does_not_throw_client_error_exception_on_4xx_error_if_only_server_exception(RequestInterface $request, ResponseInterface $response) @@ -49,7 +54,7 @@ public function it_does_not_throw_client_error_exception_on_4xx_error_if_only_se } }; - $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); + $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf(HttpFulfilledPromise::class); } public function it_throw_server_error_exception_on_5xx_error(RequestInterface $request, ResponseInterface $response) @@ -64,8 +69,8 @@ public function it_throw_server_error_exception_on_5xx_error(RequestInterface $r }; $promise = $this->handleRequest($request, $next, function () {}); - $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); - $promise->shouldThrow('Http\Client\Common\Exception\ServerErrorException')->duringWait(); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); + $promise->shouldThrow(ServerErrorException::class)->duringWait(); } public function it_returns_response(RequestInterface $request, ResponseInterface $response) @@ -78,6 +83,6 @@ public function it_returns_response(RequestInterface $request, ResponseInterface } }; - $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); + $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf(HttpFulfilledPromise::class); } } diff --git a/spec/Plugin/HeaderAppendPluginSpec.php b/spec/Plugin/HeaderAppendPluginSpec.php index bb10de1..9325069 100644 --- a/spec/Plugin/HeaderAppendPluginSpec.php +++ b/spec/Plugin/HeaderAppendPluginSpec.php @@ -2,21 +2,23 @@ namespace spec\Http\Client\Common\Plugin; -use Psr\Http\Message\RequestInterface; +use Http\Client\Common\Plugin; +use Http\Client\Common\Plugin\HeaderAppendPlugin; use PhpSpec\ObjectBehavior; +use Psr\Http\Message\RequestInterface; class HeaderAppendPluginSpec extends ObjectBehavior { public function it_is_initializable() { $this->beConstructedWith([]); - $this->shouldHaveType('Http\Client\Common\Plugin\HeaderAppendPlugin'); + $this->shouldHaveType(HeaderAppendPlugin::class); } public function it_is_a_plugin() { $this->beConstructedWith([]); - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_appends_the_header(RequestInterface $request) @@ -29,6 +31,6 @@ public function it_appends_the_header(RequestInterface $request) $request->withAddedHeader('foo', 'bar')->shouldBeCalled()->willReturn($request); $request->withAddedHeader('baz', 'qux')->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } } diff --git a/spec/Plugin/HeaderDefaultsPluginSpec.php b/spec/Plugin/HeaderDefaultsPluginSpec.php index cd407e3..5a50a9c 100644 --- a/spec/Plugin/HeaderDefaultsPluginSpec.php +++ b/spec/Plugin/HeaderDefaultsPluginSpec.php @@ -2,21 +2,23 @@ namespace spec\Http\Client\Common\Plugin; -use Psr\Http\Message\RequestInterface; +use Http\Client\Common\Plugin; +use Http\Client\Common\Plugin\HeaderDefaultsPlugin; use PhpSpec\ObjectBehavior; +use Psr\Http\Message\RequestInterface; class HeaderDefaultsPluginSpec extends ObjectBehavior { public function it_is_initializable() { $this->beConstructedWith([]); - $this->shouldHaveType('Http\Client\Common\Plugin\HeaderDefaultsPlugin'); + $this->shouldHaveType(HeaderDefaultsPlugin::class); } public function it_is_a_plugin() { $this->beConstructedWith([]); - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_sets_the_default_header(RequestInterface $request) @@ -30,6 +32,6 @@ public function it_sets_the_default_header(RequestInterface $request) $request->withHeader('foo', 'bar')->shouldBeCalled()->willReturn($request); $request->hasHeader('baz')->shouldBeCalled()->willReturn(true); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } } diff --git a/spec/Plugin/HeaderRemovePluginSpec.php b/spec/Plugin/HeaderRemovePluginSpec.php index ec6b069..3f60359 100644 --- a/spec/Plugin/HeaderRemovePluginSpec.php +++ b/spec/Plugin/HeaderRemovePluginSpec.php @@ -2,21 +2,23 @@ namespace spec\Http\Client\Common\Plugin; -use Psr\Http\Message\RequestInterface; +use Http\Client\Common\Plugin; +use Http\Client\Common\Plugin\HeaderRemovePlugin; use PhpSpec\ObjectBehavior; +use Psr\Http\Message\RequestInterface; class HeaderRemovePluginSpec extends ObjectBehavior { public function it_is_initializable() { $this->beConstructedWith([]); - $this->shouldHaveType('Http\Client\Common\Plugin\HeaderRemovePlugin'); + $this->shouldHaveType(HeaderRemovePlugin::class); } public function it_is_a_plugin() { $this->beConstructedWith([]); - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_removes_the_header(RequestInterface $request) @@ -31,6 +33,6 @@ public function it_removes_the_header(RequestInterface $request) $request->hasHeader('baz')->shouldBeCalled()->willReturn(true); $request->withoutHeader('baz')->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } } diff --git a/spec/Plugin/HeaderSetPluginSpec.php b/spec/Plugin/HeaderSetPluginSpec.php index 4e4efd0..b152567 100644 --- a/spec/Plugin/HeaderSetPluginSpec.php +++ b/spec/Plugin/HeaderSetPluginSpec.php @@ -2,21 +2,23 @@ namespace spec\Http\Client\Common\Plugin; -use Psr\Http\Message\RequestInterface; +use Http\Client\Common\Plugin; +use Http\Client\Common\Plugin\HeaderSetPlugin; use PhpSpec\ObjectBehavior; +use Psr\Http\Message\RequestInterface; class HeaderSetPluginSpec extends ObjectBehavior { public function it_is_initializable() { $this->beConstructedWith([]); - $this->shouldHaveType('Http\Client\Common\Plugin\HeaderSetPlugin'); + $this->shouldHaveType(HeaderSetPlugin::class); } public function it_is_a_plugin() { $this->beConstructedWith([]); - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_set_the_header(RequestInterface $request) @@ -29,6 +31,6 @@ public function it_set_the_header(RequestInterface $request) $request->withHeader('foo', 'bar')->shouldBeCalled()->willReturn($request); $request->withHeader('baz', 'qux')->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } } diff --git a/spec/Plugin/HistoryPluginSpec.php b/spec/Plugin/HistoryPluginSpec.php index 77682a7..495e5d5 100644 --- a/spec/Plugin/HistoryPluginSpec.php +++ b/spec/Plugin/HistoryPluginSpec.php @@ -10,6 +10,7 @@ use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; use Prophecy\Argument; +use Http\Client\Common\Plugin; class HistoryPluginSpec extends ObjectBehavior { @@ -25,7 +26,7 @@ public function it_is_initializable() public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_records_success(Journal $journal, RequestInterface $request, ResponseInterface $response) diff --git a/spec/Plugin/PluginStub.php b/spec/Plugin/PluginStub.php new file mode 100644 index 0000000..ead2a57 --- /dev/null +++ b/spec/Plugin/PluginStub.php @@ -0,0 +1,25 @@ +shouldHaveType('Http\Client\Common\Plugin\QueryDefaultsPlugin'); + $this->shouldHaveType(QueryDefaultsPlugin::class); } public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_sets_the_default_header(RequestInterface $request, UriInterface $uri) @@ -34,9 +36,7 @@ public function it_sets_the_default_header(RequestInterface $request, UriInterfa $uri->withQuery('test=true&foo=bar')->shouldBeCalled()->willReturn($uri); $request->withUri($uri)->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () { - }, function () { - }); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_replace_existing_request_value(RequestInterface $request, UriInterface $uri) @@ -51,8 +51,6 @@ public function it_does_not_replace_existing_request_value(RequestInterface $req $uri->withQuery('foo=new&bar=barDefault')->shouldBeCalled()->willReturn($uri); $request->withUri($uri)->shouldBeCalled()->willReturn($request); - $this->handleRequest($request, function () { - }, function () { - }); + $this->handleRequest($request, PluginStub::next(), function () {}); } } diff --git a/spec/Plugin/RedirectPluginSpec.php b/spec/Plugin/RedirectPluginSpec.php index 283bfb5..e24b6b1 100644 --- a/spec/Plugin/RedirectPluginSpec.php +++ b/spec/Plugin/RedirectPluginSpec.php @@ -2,25 +2,30 @@ namespace spec\Http\Client\Common\Plugin; +use Http\Client\Common\Exception\CircularRedirectionException; +use Http\Client\Common\Exception\MultipleRedirectionException; +use Http\Client\Common\Plugin; use Http\Client\Common\Plugin\RedirectPlugin; +use Http\Client\Exception\HttpException; use Http\Client\Promise\HttpFulfilledPromise; +use Http\Client\Promise\HttpRejectedPromise; use Http\Promise\Promise; +use PhpSpec\ObjectBehavior; +use Prophecy\Argument; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; -use PhpSpec\ObjectBehavior; -use Prophecy\Argument; class RedirectPluginSpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\Plugin\RedirectPlugin'); + $this->shouldHaveType(RedirectPlugin::class); } public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_redirects_on_302( @@ -64,13 +69,13 @@ public function it_redirects_on_302( $promise->wait()->shouldBeCalled()->willReturn($finalResponse); $finalPromise = $this->handleRequest($request, $next, $first); - $finalPromise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); + $finalPromise->shouldReturnAnInstanceOf(HttpFulfilledPromise::class); $finalPromise->wait()->shouldReturn($finalResponse); } public function it_use_storage_on_301(UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, RequestInterface $modifiedRequest) { - $this->beAnInstanceOf('spec\Http\Client\Common\Plugin\RedirectPluginStub'); + $this->beAnInstanceOf(RedirectPluginStub::class); $this->beConstructedWith($uriRedirect, '/original', '301'); $next = function () { @@ -86,7 +91,7 @@ public function it_use_storage_on_301(UriInterface $uri, UriInterface $uriRedire $uriRedirect->__toString()->willReturn('/redirect'); - $this->handleRequest($request, $next, function () {}); + $this->handleRequest($request, $next, PluginStub::first()); } public function it_stores_a_301( @@ -98,7 +103,7 @@ public function it_stores_a_301( ResponseInterface $finalResponse, Promise $promise ) { - $this->beAnInstanceOf('spec\Http\Client\Common\Plugin\RedirectPluginStub'); + $this->beAnInstanceOf(RedirectPluginStub::class); $this->beConstructedWith($uriRedirect, '', '301'); $request->getUri()->willReturn($uri); @@ -201,8 +206,8 @@ public function it_throws_http_exception_on_no_location(RequestInterface $reques $responseRedirect->hasHeader('Location')->willReturn(false); $promise = $this->handleRequest($request, $next, function () {}); - $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); - $promise->shouldThrow('Http\Client\Exception\HttpException')->duringWait(); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); + $promise->shouldThrow(HttpException::class)->duringWait(); } public function it_throws_http_exception_on_invalid_location(RequestInterface $request, UriInterface $uri, ResponseInterface $responseRedirect) @@ -221,8 +226,8 @@ public function it_throws_http_exception_on_invalid_location(RequestInterface $r $responseRedirect->hasHeader('Location')->willReturn(true); $promise = $this->handleRequest($request, $next, function () {}); - $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); - $promise->shouldThrow('Http\Client\Exception\HttpException')->duringWait(); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); + $promise->shouldThrow(HttpException::class)->duringWait(); } public function it_throw_multi_redirect_exception_on_300(RequestInterface $request, ResponseInterface $responseRedirect) @@ -237,8 +242,8 @@ public function it_throw_multi_redirect_exception_on_300(RequestInterface $reque $responseRedirect->getStatusCode()->willReturn('300'); $promise = $this->handleRequest($request, $next, function () {}); - $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); - $promise->shouldThrow('Http\Client\Common\Exception\MultipleRedirectionException')->duringWait(); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); + $promise->shouldThrow(MultipleRedirectionException::class)->duringWait(); } public function it_throw_multi_redirect_exception_on_300_if_no_location(RequestInterface $request, ResponseInterface $responseRedirect) @@ -253,8 +258,8 @@ public function it_throw_multi_redirect_exception_on_300_if_no_location(RequestI $responseRedirect->hasHeader('Location')->willReturn(false); $promise = $this->handleRequest($request, $next, function () {}); - $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); - $promise->shouldThrow('Http\Client\Common\Exception\MultipleRedirectionException')->duringWait(); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); + $promise->shouldThrow(MultipleRedirectionException::class)->duringWait(); } public function it_switch_method_for_302( @@ -358,7 +363,7 @@ public function it_throws_circular_redirection_exception(UriInterface $uri, UriI { $first = function () {}; - $this->beAnInstanceOf('spec\Http\Client\Common\Plugin\RedirectPluginStubCircular'); + $this->beAnInstanceOf(RedirectPluginStubCircular::class); $this->beConstructedWith(spl_object_hash((object) $first)); $request->getUri()->willReturn($uri); @@ -384,8 +389,8 @@ public function it_throws_circular_redirection_exception(UriInterface $uri, UriI }; $promise = $this->handleRequest($request, $next, $first); - $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); - $promise->shouldThrow('Http\Client\Common\Exception\CircularRedirectionException')->duringWait(); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); + $promise->shouldThrow(CircularRedirectionException::class)->duringWait(); } public function it_redirects_http_to_https( @@ -431,7 +436,7 @@ public function it_redirects_http_to_https( $promise->wait()->shouldBeCalled()->willReturn($finalResponse); $finalPromise = $this->handleRequest($request, $next, $first); - $finalPromise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); + $finalPromise->shouldReturnAnInstanceOf(HttpFulfilledPromise::class); $finalPromise->wait()->shouldReturn($finalResponse); } } diff --git a/spec/Plugin/RequestMatcherPluginSpec.php b/spec/Plugin/RequestMatcherPluginSpec.php index bd4e7e4..de7cae6 100644 --- a/spec/Plugin/RequestMatcherPluginSpec.php +++ b/spec/Plugin/RequestMatcherPluginSpec.php @@ -8,6 +8,7 @@ use Psr\Http\Message\RequestInterface; use PhpSpec\ObjectBehavior; use Prophecy\Argument; +use Http\Client\Common\Plugin\RequestMatcherPlugin; class RequestMatcherPluginSpec extends ObjectBehavior { @@ -18,12 +19,12 @@ public function let(RequestMatcher $requestMatcher, Plugin $plugin) public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\Plugin\RequestMatcherPlugin'); + $this->shouldHaveType(RequestMatcherPlugin::class); } public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_matches_a_request_and_delegates_to_plugin( @@ -34,7 +35,7 @@ public function it_matches_a_request_and_delegates_to_plugin( $requestMatcher->matches($request)->willReturn(true); $plugin->handleRequest($request, Argument::type('callable'), Argument::type('callable'))->shouldBeCalled(); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_does_not_match_a_request( diff --git a/spec/Plugin/RetryPluginSpec.php b/spec/Plugin/RetryPluginSpec.php index c439cad..682b892 100644 --- a/spec/Plugin/RetryPluginSpec.php +++ b/spec/Plugin/RetryPluginSpec.php @@ -9,17 +9,19 @@ use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; use Prophecy\Argument; +use Http\Client\Common\Plugin\RetryPlugin; +use Http\Client\Common\Plugin; class RetryPluginSpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\Plugin\RetryPlugin'); + $this->shouldHaveType(RetryPlugin::class); } public function it_is_a_plugin() { - $this->shouldImplement('Http\Client\Common\Plugin'); + $this->shouldImplement(Plugin::class); } public function it_returns_response(RequestInterface $request, ResponseInterface $response) @@ -30,7 +32,7 @@ public function it_returns_response(RequestInterface $request, ResponseInterface } }; - $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); + $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf(HttpFulfilledPromise::class); } public function it_throws_exception_on_multiple_exceptions(RequestInterface $request) @@ -53,7 +55,7 @@ public function it_throws_exception_on_multiple_exceptions(RequestInterface $req }; $promise = $this->handleRequest($request, $next, function () {}); - $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise'); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); $promise->shouldThrow($exception2)->duringWait(); } @@ -76,7 +78,7 @@ public function it_returns_response_on_second_try(RequestInterface $request, Res }; $promise = $this->handleRequest($request, $next, function () {}); - $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); + $promise->shouldReturnAnInstanceOf(HttpFulfilledPromise::class); $promise->wait()->shouldReturn($response); } @@ -98,8 +100,8 @@ public function it_does_not_keep_history_of_old_failure(RequestInterface $reques } }; - $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); - $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise'); + $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf(HttpFulfilledPromise::class); + $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf(HttpFulfilledPromise::class); } public function it_has_an_exponential_default_delay(RequestInterface $request, Exception\HttpException $exception) diff --git a/spec/PluginClientFactorySpec.php b/spec/PluginClientFactorySpec.php index fe7e076..d7a3acb 100644 --- a/spec/PluginClientFactorySpec.php +++ b/spec/PluginClientFactorySpec.php @@ -4,19 +4,21 @@ use Http\Client\HttpClient; use PhpSpec\ObjectBehavior; +use Http\Client\Common\PluginClientFactory; +use Http\Client\Common\PluginClient; class PluginClientFactorySpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\PluginClientFactory'); + $this->shouldHaveType(PluginClientFactory::class); } public function it_returns_a_plugin_client(HttpClient $httpClient) { $client = $this->createClient($httpClient); - $client->shouldHaveType('Http\Client\Common\PluginClient'); + $client->shouldHaveType(PluginClient::class); } public function it_does_not_construct_plugin_client_with_client_name_option(HttpClient $httpClient) diff --git a/spec/PluginClientSpec.php b/spec/PluginClientSpec.php index 50df636..c5c2932 100644 --- a/spec/PluginClientSpec.php +++ b/spec/PluginClientSpec.php @@ -10,6 +10,8 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; +use Http\Client\Common\Exception\LoopException; +use Http\Client\Common\PluginClient; class PluginClientSpec extends ObjectBehavior { @@ -20,17 +22,17 @@ public function let(HttpClient $httpClient) public function it_is_initializable() { - $this->shouldHaveType('Http\Client\Common\PluginClient'); + $this->shouldHaveType(PluginClient::class); } public function it_is_an_http_client() { - $this->shouldImplement('Http\Client\HttpClient'); + $this->shouldImplement(HttpClient::class); } public function it_is_an_http_async_client() { - $this->shouldImplement('Http\Client\HttpAsyncClient'); + $this->shouldImplement(HttpAsyncClient::class); } public function it_sends_request_with_underlying_client(HttpClient $httpClient, RequestInterface $request, ResponseInterface $response) @@ -59,8 +61,8 @@ public function it_sends_async_request_if_no_send_request(HttpAsyncClient $httpA public function it_prefers_send_request($client, RequestInterface $request, ResponseInterface $response) { - $client->implement('Http\Client\HttpClient'); - $client->implement('Http\Client\HttpAsyncClient'); + $client->implement(HttpClient::class); + $client->implement(HttpAsyncClient::class); $client->sendRequest($request)->willReturn($response); @@ -84,6 +86,6 @@ public function it_throws_loop_exception(HttpClient $httpClient, RequestInterfac $this->beConstructedWith($httpClient, [$plugin]); - $this->shouldThrow('Http\Client\Common\Exception\LoopException')->duringSendRequest($request); + $this->shouldThrow(LoopException::class)->duringSendRequest($request); } } diff --git a/src/BatchClient.php b/src/BatchClient.php index 7ddba4e..8dfeb81 100644 --- a/src/BatchClient.php +++ b/src/BatchClient.php @@ -49,7 +49,7 @@ public function sendRequest(RequestInterface $request): ResponseInterface * BatchResult with a map of request to result for success, request to * exception for failures */ - public function sendRequests(array $requests) + public function sendRequests(array $requests): BatchResult { $batchResult = new BatchResult(); diff --git a/src/BatchResult.php b/src/BatchResult.php index 3f8a2f0..94ff51a 100644 --- a/src/BatchResult.php +++ b/src/BatchResult.php @@ -31,10 +31,8 @@ public function __construct() /** * Checks if there are any successful responses at all. - * - * @return bool */ - public function hasResponses() + public function hasResponses(): bool { return $this->responses->count() > 0; } @@ -44,7 +42,7 @@ public function hasResponses() * * @return ResponseInterface[] */ - public function getResponses() + public function getResponses(): array { $responses = []; @@ -57,10 +55,8 @@ public function getResponses() /** * Checks if there is a successful response for a request. - * - * @return bool */ - public function isSuccessful(RequestInterface $request) + public function isSuccessful(RequestInterface $request): bool { return $this->responses->contains($request); } @@ -68,11 +64,10 @@ public function isSuccessful(RequestInterface $request) /** * Returns the response for a successful request. * - * @return ResponseInterface * * @throws \UnexpectedValueException If request was not part of the batch or failed */ - public function getResponseFor(RequestInterface $request) + public function getResponseFor(RequestInterface $request): ResponseInterface { try { return $this->responses[$request]; @@ -86,7 +81,7 @@ public function getResponseFor(RequestInterface $request) * * @return BatchResult the new BatchResult with this request-response pair added to it */ - public function addResponse(RequestInterface $request, ResponseInterface $response) + public function addResponse(RequestInterface $request, ResponseInterface $response): self { $new = clone $this; $new->responses->attach($request, $response); @@ -96,10 +91,8 @@ public function addResponse(RequestInterface $request, ResponseInterface $respon /** * Checks if there are any unsuccessful requests at all. - * - * @return bool */ - public function hasExceptions() + public function hasExceptions(): bool { return $this->exceptions->count() > 0; } @@ -109,7 +102,7 @@ public function hasExceptions() * * @return Exception[] */ - public function getExceptions() + public function getExceptions(): array { $exceptions = []; @@ -122,10 +115,8 @@ public function getExceptions() /** * Checks if there is an exception for a request, meaning the request failed. - * - * @return bool */ - public function isFailed(RequestInterface $request) + public function isFailed(RequestInterface $request): bool { return $this->exceptions->contains($request); } @@ -133,11 +124,10 @@ public function isFailed(RequestInterface $request) /** * Returns the exception for a failed request. * - * @return Exception * * @throws \UnexpectedValueException If request was not part of the batch or was successful */ - public function getExceptionFor(RequestInterface $request) + public function getExceptionFor(RequestInterface $request): Exception { try { return $this->exceptions[$request]; @@ -151,7 +141,7 @@ public function getExceptionFor(RequestInterface $request) * * @return BatchResult the new BatchResult with this request-exception pair added to it */ - public function addException(RequestInterface $request, Exception $exception) + public function addException(RequestInterface $request, Exception $exception): self { $new = clone $this; $new->exceptions->attach($request, $exception); diff --git a/src/Deferred.php b/src/Deferred.php index 075a30e..7413451 100644 --- a/src/Deferred.php +++ b/src/Deferred.php @@ -34,7 +34,7 @@ public function __construct(callable $waitCallback) /** * {@inheritdoc} */ - public function then(callable $onFulfilled = null, callable $onRejected = null) + public function then(callable $onFulfilled = null, callable $onRejected = null): Promise { $deferred = new self($this->waitCallback); @@ -69,7 +69,7 @@ public function then(callable $onFulfilled = null, callable $onRejected = null) /** * {@inheritdoc} */ - public function getState() + public function getState(): string { return $this->state; } diff --git a/src/HttpClientPool.php b/src/HttpClientPool.php index 6f4597f..90a8464 100644 --- a/src/HttpClientPool.php +++ b/src/HttpClientPool.php @@ -40,7 +40,7 @@ public function addHttpClient($client) * * @return HttpClientPoolItem Return a http client that can do both sync or async */ - abstract protected function chooseHttpClient(); + abstract protected function chooseHttpClient(): HttpClientPoolItem; /** * {@inheritdoc} diff --git a/src/HttpClientPool/LeastUsedClientPool.php b/src/HttpClientPool/LeastUsedClientPool.php index 6299cce..61eb670 100644 --- a/src/HttpClientPool/LeastUsedClientPool.php +++ b/src/HttpClientPool/LeastUsedClientPool.php @@ -18,7 +18,7 @@ final class LeastUsedClientPool extends HttpClientPool /** * {@inheritdoc} */ - protected function chooseHttpClient() + protected function chooseHttpClient(): HttpClientPoolItem { $clientPool = array_filter($this->clientPool, function (HttpClientPoolItem $clientPoolItem) { return !$clientPoolItem->isDisabled(); diff --git a/src/HttpClientPool/RandomClientPool.php b/src/HttpClientPool/RandomClientPool.php index 3255f86..2889ed7 100644 --- a/src/HttpClientPool/RandomClientPool.php +++ b/src/HttpClientPool/RandomClientPool.php @@ -16,7 +16,7 @@ final class RandomClientPool extends HttpClientPool /** * {@inheritdoc} */ - protected function chooseHttpClient() + protected function chooseHttpClient(): HttpClientPoolItem { $clientPool = array_filter($this->clientPool, function (HttpClientPoolItem $clientPoolItem) { return !$clientPoolItem->isDisabled(); diff --git a/src/HttpClientPool/RoundRobinClientPool.php b/src/HttpClientPool/RoundRobinClientPool.php index 8d8e40a..3315b51 100644 --- a/src/HttpClientPool/RoundRobinClientPool.php +++ b/src/HttpClientPool/RoundRobinClientPool.php @@ -4,6 +4,7 @@ use Http\Client\Common\Exception\HttpClientNotFoundException; use Http\Client\Common\HttpClientPool; +use Http\Client\Common\HttpClientPoolItem; /** * RoundRobinClientPool will choose the next client in the pool. @@ -15,7 +16,7 @@ final class RoundRobinClientPool extends HttpClientPool /** * {@inheritdoc} */ - protected function chooseHttpClient() + protected function chooseHttpClient(): HttpClientPoolItem { $last = current($this->clientPool); diff --git a/src/HttpMethodsClient.php b/src/HttpMethodsClient.php index a1ef2c8..bc02ef8 100644 --- a/src/HttpMethodsClient.php +++ b/src/HttpMethodsClient.php @@ -52,10 +52,8 @@ public function __construct(HttpClient $httpClient, RequestFactory $requestFacto * @param string|UriInterface $uri * * @throws Exception - * - * @return ResponseInterface */ - public function get($uri, array $headers = []) + public function get($uri, array $headers = []): ResponseInterface { return $this->send('GET', $uri, $headers, null); } @@ -66,10 +64,8 @@ public function get($uri, array $headers = []) * @param string|UriInterface $uri * * @throws Exception - * - * @return ResponseInterface */ - public function head($uri, array $headers = []) + public function head($uri, array $headers = []): ResponseInterface { return $this->send('HEAD', $uri, $headers, null); } @@ -80,10 +76,8 @@ public function head($uri, array $headers = []) * @param string|UriInterface $uri * * @throws Exception - * - * @return ResponseInterface */ - public function trace($uri, array $headers = []) + public function trace($uri, array $headers = []): ResponseInterface { return $this->send('TRACE', $uri, $headers, null); } @@ -95,10 +89,8 @@ public function trace($uri, array $headers = []) * @param string|StreamInterface|null $body * * @throws Exception - * - * @return ResponseInterface */ - public function post($uri, array $headers = [], $body = null) + public function post($uri, array $headers = [], $body = null): ResponseInterface { return $this->send('POST', $uri, $headers, $body); } @@ -110,10 +102,8 @@ public function post($uri, array $headers = [], $body = null) * @param string|StreamInterface|null $body * * @throws Exception - * - * @return ResponseInterface */ - public function put($uri, array $headers = [], $body = null) + public function put($uri, array $headers = [], $body = null): ResponseInterface { return $this->send('PUT', $uri, $headers, $body); } @@ -125,10 +115,8 @@ public function put($uri, array $headers = [], $body = null) * @param string|StreamInterface|null $body * * @throws Exception - * - * @return ResponseInterface */ - public function patch($uri, array $headers = [], $body = null) + public function patch($uri, array $headers = [], $body = null): ResponseInterface { return $this->send('PATCH', $uri, $headers, $body); } @@ -140,10 +128,8 @@ public function patch($uri, array $headers = [], $body = null) * @param string|StreamInterface|null $body * * @throws Exception - * - * @return ResponseInterface */ - public function delete($uri, array $headers = [], $body = null) + public function delete($uri, array $headers = [], $body = null): ResponseInterface { return $this->send('DELETE', $uri, $headers, $body); } @@ -155,10 +141,8 @@ public function delete($uri, array $headers = [], $body = null) * @param string|StreamInterface|null $body * * @throws Exception - * - * @return ResponseInterface */ - public function options($uri, array $headers = [], $body = null) + public function options($uri, array $headers = [], $body = null): ResponseInterface { return $this->send('OPTIONS', $uri, $headers, $body); } @@ -171,10 +155,8 @@ public function options($uri, array $headers = [], $body = null) * @param string|StreamInterface|null $body * * @throws Exception - * - * @return ResponseInterface */ - public function send($method, $uri, array $headers = [], $body = null) + public function send($method, $uri, array $headers = [], $body = null): ResponseInterface { return $this->sendRequest($this->requestFactory->createRequest( $method, diff --git a/src/Plugin.php b/src/Plugin.php index bfb2668..ab7e4a1 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -27,5 +27,5 @@ interface Plugin * * @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception (The same as HttpAsyncClient) */ - public function handleRequest(RequestInterface $request, callable $next, callable $first); + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise; } diff --git a/src/Plugin/AddHostPlugin.php b/src/Plugin/AddHostPlugin.php index 050feb1..492667e 100644 --- a/src/Plugin/AddHostPlugin.php +++ b/src/Plugin/AddHostPlugin.php @@ -3,6 +3,7 @@ namespace Http\Client\Common\Plugin; use Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -48,7 +49,7 @@ public function __construct(UriInterface $host, array $config = []) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { if ($this->replace || '' === $request->getUri()->getHost()) { $uri = $request->getUri() diff --git a/src/Plugin/AddPathPlugin.php b/src/Plugin/AddPathPlugin.php index 1675088..ae5d97d 100644 --- a/src/Plugin/AddPathPlugin.php +++ b/src/Plugin/AddPathPlugin.php @@ -3,6 +3,7 @@ namespace Http\Client\Common\Plugin; use Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; @@ -41,7 +42,7 @@ public function __construct(UriInterface $uri) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { $identifier = spl_object_hash((object) $first); diff --git a/src/Plugin/AuthenticationPlugin.php b/src/Plugin/AuthenticationPlugin.php index ff33f9b..5b6c447 100644 --- a/src/Plugin/AuthenticationPlugin.php +++ b/src/Plugin/AuthenticationPlugin.php @@ -4,6 +4,7 @@ use Http\Client\Common\Plugin; use Http\Message\Authentication; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; /** @@ -26,7 +27,7 @@ public function __construct(Authentication $authentication) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { $request = $this->authentication->authenticate($request); diff --git a/src/Plugin/BaseUriPlugin.php b/src/Plugin/BaseUriPlugin.php index 669c308..ee9e075 100644 --- a/src/Plugin/BaseUriPlugin.php +++ b/src/Plugin/BaseUriPlugin.php @@ -3,6 +3,7 @@ namespace Http\Client\Common\Plugin; use Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\UriInterface; @@ -39,7 +40,7 @@ public function __construct(UriInterface $uri, array $hostConfig = []) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { $addHostNext = function (RequestInterface $request) use ($next, $first) { return $this->addHostPlugin->handleRequest($request, $next, $first); diff --git a/src/Plugin/ContentLengthPlugin.php b/src/Plugin/ContentLengthPlugin.php index 0f7aafa..dff2ca8 100644 --- a/src/Plugin/ContentLengthPlugin.php +++ b/src/Plugin/ContentLengthPlugin.php @@ -4,6 +4,7 @@ use Http\Client\Common\Plugin; use Http\Message\Encoding\ChunkStream; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; /** @@ -16,7 +17,7 @@ final class ContentLengthPlugin implements Plugin /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { if (!$request->hasHeader('Content-Length')) { $stream = $request->getBody(); diff --git a/src/Plugin/ContentTypePlugin.php b/src/Plugin/ContentTypePlugin.php index d0bfa8d..190f125 100644 --- a/src/Plugin/ContentTypePlugin.php +++ b/src/Plugin/ContentTypePlugin.php @@ -3,6 +3,7 @@ namespace Http\Client\Common\Plugin; use Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\StreamInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -57,7 +58,7 @@ public function __construct(array $config = []) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { if (!$request->hasHeader('Content-Type')) { $stream = $request->getBody(); @@ -93,10 +94,8 @@ public function handleRequest(RequestInterface $request, callable $next, callabl /** * @param $stream StreamInterface - * - * @return bool */ - private function isJson($stream) + private function isJson($stream): bool { $stream->rewind(); diff --git a/src/Plugin/CookiePlugin.php b/src/Plugin/CookiePlugin.php index 3ab5388..84669cf 100644 --- a/src/Plugin/CookiePlugin.php +++ b/src/Plugin/CookiePlugin.php @@ -8,6 +8,7 @@ use Http\Message\CookieJar; use Http\Message\CookieUtil; use Http\Message\Exception\UnexpectedValueException; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -33,7 +34,7 @@ public function __construct(CookieJar $cookieJar) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { $cookies = []; foreach ($this->cookieJar->getCookies() as $cookie) { @@ -99,7 +100,7 @@ private function createCookie(RequestInterface $request, $setCookie) $parts = array_map('trim', explode(';', $setCookie)); if (empty($parts) || !strpos($parts[0], '=')) { - return; + return null; } list($name, $cookieValue) = $this->createValueKey(array_shift($parts)); diff --git a/src/Plugin/DecoderPlugin.php b/src/Plugin/DecoderPlugin.php index 3a28f5b..0930779 100644 --- a/src/Plugin/DecoderPlugin.php +++ b/src/Plugin/DecoderPlugin.php @@ -4,6 +4,7 @@ use Http\Client\Common\Plugin; use Http\Message\Encoding; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; @@ -48,7 +49,7 @@ public function __construct(array $config = []) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { $encodings = extension_loaded('zlib') ? ['gzip', 'deflate'] : ['identity']; diff --git a/src/Plugin/ErrorPlugin.php b/src/Plugin/ErrorPlugin.php index 4fd7201..1d25fb7 100644 --- a/src/Plugin/ErrorPlugin.php +++ b/src/Plugin/ErrorPlugin.php @@ -5,6 +5,7 @@ use Http\Client\Common\Exception\ClientErrorException; use Http\Client\Common\Exception\ServerErrorException; use Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -46,7 +47,7 @@ public function __construct(array $config = []) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { $promise = $next($request); @@ -66,7 +67,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl * * @return ResponseInterface If status code is not in 4xx or 5xx return response */ - private function transformResponseToException(RequestInterface $request, ResponseInterface $response) + private function transformResponseToException(RequestInterface $request, ResponseInterface $response): ResponseInterface { if (!$this->onlyServerException && $response->getStatusCode() >= 400 && $response->getStatusCode() < 500) { throw new ClientErrorException($response->getReasonPhrase(), $request, $response); diff --git a/src/Plugin/HeaderAppendPlugin.php b/src/Plugin/HeaderAppendPlugin.php index 26fd813..ca44836 100644 --- a/src/Plugin/HeaderAppendPlugin.php +++ b/src/Plugin/HeaderAppendPlugin.php @@ -3,6 +3,7 @@ namespace Http\Client\Common\Plugin; use Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; /** @@ -21,7 +22,7 @@ final class HeaderAppendPlugin implements Plugin /** * @var array */ - private $headers = []; + private $headers; /** * @param array $headers Hashmap of header name to header value @@ -34,7 +35,7 @@ public function __construct(array $headers) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { foreach ($this->headers as $header => $headerValue) { $request = $request->withAddedHeader($header, $headerValue); diff --git a/src/Plugin/HeaderDefaultsPlugin.php b/src/Plugin/HeaderDefaultsPlugin.php index 6dfc111..77ffe8c 100644 --- a/src/Plugin/HeaderDefaultsPlugin.php +++ b/src/Plugin/HeaderDefaultsPlugin.php @@ -3,6 +3,7 @@ namespace Http\Client\Common\Plugin; use Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; /** @@ -30,7 +31,7 @@ public function __construct(array $headers) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { foreach ($this->headers as $header => $headerValue) { if (!$request->hasHeader($header)) { diff --git a/src/Plugin/HeaderRemovePlugin.php b/src/Plugin/HeaderRemovePlugin.php index fc9c19d..0a34248 100644 --- a/src/Plugin/HeaderRemovePlugin.php +++ b/src/Plugin/HeaderRemovePlugin.php @@ -3,6 +3,7 @@ namespace Http\Client\Common\Plugin; use Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; /** @@ -28,7 +29,7 @@ public function __construct(array $headers) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { foreach ($this->headers as $header) { if ($request->hasHeader($header)) { diff --git a/src/Plugin/HeaderSetPlugin.php b/src/Plugin/HeaderSetPlugin.php index 75f11d4..210bb42 100644 --- a/src/Plugin/HeaderSetPlugin.php +++ b/src/Plugin/HeaderSetPlugin.php @@ -3,6 +3,7 @@ namespace Http\Client\Common\Plugin; use Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; /** @@ -17,7 +18,7 @@ final class HeaderSetPlugin implements Plugin /** * @var array */ - private $headers = []; + private $headers; /** * @param array $headers Hashmap of header name to header value @@ -30,7 +31,7 @@ public function __construct(array $headers) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { foreach ($this->headers as $header => $headerValue) { $request = $request->withHeader($header, $headerValue); diff --git a/src/Plugin/HistoryPlugin.php b/src/Plugin/HistoryPlugin.php index 0c59a2a..7b14485 100644 --- a/src/Plugin/HistoryPlugin.php +++ b/src/Plugin/HistoryPlugin.php @@ -4,6 +4,7 @@ use Http\Client\Common\Plugin; use Http\Client\Exception; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -29,7 +30,7 @@ public function __construct(Journal $journal) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { $journal = $this->journal; diff --git a/src/Plugin/QueryDefaultsPlugin.php b/src/Plugin/QueryDefaultsPlugin.php index d9c06d6..2693507 100644 --- a/src/Plugin/QueryDefaultsPlugin.php +++ b/src/Plugin/QueryDefaultsPlugin.php @@ -3,6 +3,7 @@ namespace Http\Client\Common\Plugin; use Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; /** @@ -31,7 +32,7 @@ public function __construct(array $queryParams) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { $uri = $request->getUri(); diff --git a/src/Plugin/RedirectPlugin.php b/src/Plugin/RedirectPlugin.php index d2f442e..80c5251 100644 --- a/src/Plugin/RedirectPlugin.php +++ b/src/Plugin/RedirectPlugin.php @@ -6,6 +6,7 @@ use Http\Client\Common\Exception\MultipleRedirectionException; use Http\Client\Common\Plugin; use Http\Client\Exception\HttpException; +use Http\Promise\Promise; use Psr\Http\Message\MessageInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -131,7 +132,7 @@ public function __construct(array $config = []) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { // Check in storage if (array_key_exists((string) $request->getUri(), $this->redirectStorage)) { @@ -215,10 +216,8 @@ protected function buildRedirectRequest(RequestInterface $request, UriInterface * * @throws HttpException If location header is not usable (missing or incorrect) * @throws MultipleRedirectionException If a 300 status code is received and default location cannot be resolved (doesn't use the location header or not present) - * - * @return UriInterface */ - private function createUri(ResponseInterface $response, RequestInterface $request) + private function createUri(ResponseInterface $response, RequestInterface $request): UriInterface { if ($this->redirectCodes[$response->getStatusCode()]['multiple'] && (!$this->useDefaultForMultiple || !$response->hasHeader('Location'))) { throw new MultipleRedirectionException('Cannot choose a redirection', $request, $response); diff --git a/src/Plugin/RequestMatcherPlugin.php b/src/Plugin/RequestMatcherPlugin.php index dd97b3c..d7d3f3d 100644 --- a/src/Plugin/RequestMatcherPlugin.php +++ b/src/Plugin/RequestMatcherPlugin.php @@ -4,6 +4,7 @@ use Http\Client\Common\Plugin; use Http\Message\RequestMatcher; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; /** @@ -32,7 +33,7 @@ public function __construct(RequestMatcher $requestMatcher, Plugin $delegatedPlu /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { if ($this->requestMatcher->matches($request)) { return $this->delegatedPlugin->handleRequest($request, $next, $first); diff --git a/src/Plugin/RetryPlugin.php b/src/Plugin/RetryPlugin.php index 96cfbb2..c10bce4 100644 --- a/src/Plugin/RetryPlugin.php +++ b/src/Plugin/RetryPlugin.php @@ -4,6 +4,7 @@ use Http\Client\Common\Plugin; use Http\Client\Exception; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -72,7 +73,7 @@ public function __construct(array $config = []) /** * {@inheritdoc} */ - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { $chainIdentifier = spl_object_hash((object) $first); diff --git a/src/PluginClient.php b/src/PluginClient.php index 6881c93..264c2fe 100644 --- a/src/PluginClient.php +++ b/src/PluginClient.php @@ -101,10 +101,8 @@ public function sendAsyncRequest(RequestInterface $request) /** * Configure the plugin client. - * - * @return array */ - private function configure(array $options = []) + private function configure(array $options = []): array { $resolver = new OptionsResolver(); $resolver->setDefaults([ @@ -121,10 +119,8 @@ private function configure(array $options = []) * * @param Plugin[] $pluginList A list of plugins * @param callable $clientCallable Callable making the HTTP call - * - * @return callable */ - private function createPluginChain($pluginList, callable $clientCallable) + private function createPluginChain(array $pluginList, callable $clientCallable): callable { $firstCallable = $lastCallable = $clientCallable; diff --git a/src/PluginClientFactory.php b/src/PluginClientFactory.php index a262f80..77642ea 100644 --- a/src/PluginClientFactory.php +++ b/src/PluginClientFactory.php @@ -42,10 +42,8 @@ public static function setFactory(callable $factory) * } * * @see PluginClient constructor for PluginClient specific $options. - * - * @return PluginClient */ - public function createClient($client, array $plugins = [], array $options = []) + public function createClient($client, array $plugins = [], array $options = []): PluginClient { if (static::$factory) { $factory = static::$factory; From 14a2a396652560a3037912915fdeb10239398c72 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Thu, 22 Nov 2018 10:39:42 +0100 Subject: [PATCH 12/28] Update phpcs --- .gitignore | 3 ++- .php_cs | 22 ---------------------- .php_cs.dist | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+), 23 deletions(-) delete mode 100644 .php_cs create mode 100644 .php_cs.dist diff --git a/.gitignore b/.gitignore index 560b927..8ce13f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ +/.php_cs +/.php_cs.cache /behat.yml /build/ /composer.lock /phpspec.yml /phpunit.xml /vendor/ -/.php_cs.cache diff --git a/.php_cs b/.php_cs deleted file mode 100644 index 7039b1e..0000000 --- a/.php_cs +++ /dev/null @@ -1,22 +0,0 @@ -setRules([ - '@PSR2' => true, - '@Symfony' => true, - 'array_syntax' => [ - 'syntax' => 'short', - ], - 'no_empty_phpdoc' => true, - 'no_superfluous_phpdoc_tags' => true, -]); - -$finder = PhpCsFixer\Finder::create(); -$finder->in([ - 'src', - 'spec' -]); - -$config->setFinder($finder); - -return $config; diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 0000000..b241e67 --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,23 @@ +in('src') + ->in('spec') +; +return PhpCsFixer\Config::create() + ->setRules([ + '@PSR2' => true, + '@Symfony' => true, + 'array_syntax' => [ + 'syntax' => 'short', + ], + 'no_empty_phpdoc' => true, + 'no_superfluous_phpdoc_tags' => true, + ]) + ->setFinder($finder); From 8616247dbf1a9c1b073b3a62f45055efbd129c97 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Tue, 4 Dec 2018 16:37:28 +0100 Subject: [PATCH 13/28] make redirect plugin final and refactor phpspec test to support that --- spec/Plugin/RedirectPluginSpec.php | 228 +++++++++++++++++------------ src/Plugin/RedirectPlugin.php | 18 +-- 2 files changed, 141 insertions(+), 105 deletions(-) diff --git a/spec/Plugin/RedirectPluginSpec.php b/spec/Plugin/RedirectPluginSpec.php index e24b6b1..de9b30a 100644 --- a/spec/Plugin/RedirectPluginSpec.php +++ b/spec/Plugin/RedirectPluginSpec.php @@ -73,50 +73,19 @@ public function it_redirects_on_302( $finalPromise->wait()->shouldReturn($finalResponse); } - public function it_use_storage_on_301(UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, RequestInterface $modifiedRequest) - { - $this->beAnInstanceOf(RedirectPluginStub::class); - $this->beConstructedWith($uriRedirect, '/original', '301'); - - $next = function () { - throw new \Exception('Must not be called'); - }; - - $request->getUri()->willReturn($uri); - $uri->__toString()->willReturn('/original'); - $request->withUri($uriRedirect)->willReturn($modifiedRequest); - - $modifiedRequest->getUri()->willReturn($uriRedirect); - $modifiedRequest->getMethod()->willReturn('GET'); - - $uriRedirect->__toString()->willReturn('/redirect'); - - $this->handleRequest($request, $next, PluginStub::first()); - } - - public function it_stores_a_301( + public function it_use_storage_on_301( UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, - ResponseInterface $responseRedirect, RequestInterface $modifiedRequest, ResponseInterface $finalResponse, - Promise $promise + ResponseInterface $redirectResponse ) { - $this->beAnInstanceOf(RedirectPluginStub::class); - $this->beConstructedWith($uriRedirect, '', '301'); - $request->getUri()->willReturn($uri); - $uri->__toString()->willReturn('/301-url'); - - $responseRedirect->getStatusCode()->willReturn('301'); - $responseRedirect->hasHeader('Location')->willReturn(true); - $responseRedirect->getHeaderLine('Location')->willReturn('/redirect'); - + $uri->__toString()->willReturn('/original'); $uri->withPath('/redirect')->willReturn($uriRedirect); - $uriRedirect->withFragment('')->willReturn($uriRedirect); $uriRedirect->withQuery('')->willReturn($uriRedirect); - + $uriRedirect->withFragment('')->willReturn($uriRedirect); $request->withUri($uriRedirect)->willReturn($modifiedRequest); $modifiedRequest->getUri()->willReturn($uriRedirect); @@ -124,23 +93,55 @@ public function it_stores_a_301( $uriRedirect->__toString()->willReturn('/redirect'); - $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { - if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { - return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); - } - }; + $finalResponse->getStatusCode()->willReturn(200); - $first = function (RequestInterface $receivedRequest) use ($modifiedRequest, $promise) { - if (Argument::is($modifiedRequest->getWrappedObject())->scoreArgument($receivedRequest)) { - return $promise->getWrappedObject(); + $redirectResponse->getStatusCode()->willReturn(301); + $redirectResponse->hasHeader('Location')->willReturn(true); + $redirectResponse->getHeaderLine('Location')->willReturn('/redirect'); + + $nextCalled = false; + $next = function (RequestInterface $request) use (&$nextCalled, $finalResponse, $redirectResponse): Promise { + switch ($request->getUri()) { + case '/original': + if ($nextCalled) { + throw new \Exception('Must only be called once'); + } + $nextCalled = true; + + return new HttpFulfilledPromise($redirectResponse->getWrappedObject()); + case '/redirect': + + return new HttpFulfilledPromise($finalResponse->getWrappedObject()); + default: + throw new \Exception('Test setup error with request uri '.$request->getUri()); } }; + $first = $this->buildFirst($modifiedRequest, $next); - $promise->getState()->willReturn(Promise::FULFILLED); - $promise->wait()->shouldBeCalled()->willReturn($finalResponse); + $this->handleRequest($request, $next, $first); + // rebuild first as this is expected to be called again + $first = $this->buildFirst($modifiedRequest, $next); + // next should not be called again $this->handleRequest($request, $next, $first); - $this->hasStorage('/301-url')->shouldReturn(true); + } + + private function buildFirst(RequestInterface $modifiedRequest, callable $next): callable + { + $redirectPlugin = $this; + $firstCalled = false; + + return function (RequestInterface $request) use (&$modifiedRequest, $redirectPlugin, $next, &$firstCalled) { + if ($firstCalled) { + throw new \Exception('Only one restart expected'); + } + $firstCalled = true; + if ($modifiedRequest->getWrappedObject() !== $request) { + //throw new \Exception('Redirection failed'); + } + + return $redirectPlugin->getWrappedObject()->handleRequest($request, $next, $this); + }; } public function it_replace_full_url( @@ -359,35 +360,100 @@ public function it_clears_headers( $this->handleRequest($request, $next, $first); } - public function it_throws_circular_redirection_exception(UriInterface $uri, UriInterface $uriRedirect, RequestInterface $request, ResponseInterface $responseRedirect, RequestInterface $modifiedRequest) - { - $first = function () {}; + /** + * This is the "redirection does not redirect case. + */ + public function it_throws_circular_redirection_exception_on_redirect_that_does_not_change_url( + UriInterface $redirectUri, + RequestInterface $request, + ResponseInterface $redirectResponse + ) { + $redirectResponse->getStatusCode()->willReturn(302); + $redirectResponse->hasHeader('Location')->willReturn(true); + $redirectResponse->getHeaderLine('Location')->willReturn('/redirect'); - $this->beAnInstanceOf(RedirectPluginStubCircular::class); - $this->beConstructedWith(spl_object_hash((object) $first)); + $next = function () use ($redirectResponse): Promise { + return new HttpFulfilledPromise($redirectResponse->getWrappedObject()); + }; - $request->getUri()->willReturn($uri); - $uri->__toString()->willReturn('/original'); + $first = function () { + throw new \Exception('First should never be called'); + }; - $responseRedirect->getStatusCode()->willReturn('302'); - $responseRedirect->hasHeader('Location')->willReturn(true); - $responseRedirect->getHeaderLine('Location')->willReturn('/redirect'); + $request->getUri()->willReturn($redirectUri); + $redirectUri->__toString()->willReturn('/redirect'); - $uri->withPath('/redirect')->willReturn($uriRedirect); - $uriRedirect->withFragment('')->willReturn($uriRedirect); - $uriRedirect->withQuery('')->willReturn($uriRedirect); + $redirectUri->withPath('/redirect')->willReturn($redirectUri); + $redirectUri->withFragment('')->willReturn($redirectUri); + $redirectUri->withQuery('')->willReturn($redirectUri); - $request->withUri($uriRedirect)->willReturn($modifiedRequest); - $modifiedRequest->getUri()->willReturn($uriRedirect); - $uriRedirect->__toString()->willReturn('/redirect'); - $modifiedRequest->getMethod()->willReturn('GET'); + $request->withUri($redirectUri)->willReturn($request); + $redirectUri->__toString()->willReturn('/redirect'); + $request->getMethod()->willReturn('GET'); - $next = function (RequestInterface $receivedRequest) use ($request, $responseRedirect) { - if (Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { - return new HttpFulfilledPromise($responseRedirect->getWrappedObject()); + $promise = $this->handleRequest($request, $next, $first); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); + $promise->shouldThrow(CircularRedirectionException::class)->duringWait(); + } + + /** + * This is a redirection flipping back and forth between two paths. + * + * There could be a larger loop but the logic in the plugin stays the same with as many redirects as needed. + */ + public function it_throws_circular_redirection_exception_on_alternating_redirect( + UriInterface $uri, + UriInterface $redirectUri, + RequestInterface $request, + ResponseInterface $redirectResponse1, + ResponseInterface $redirectResponse2, + RequestInterface $modifiedRequest + ) { + $redirectResponse1->getStatusCode()->willReturn(302); + $redirectResponse1->hasHeader('Location')->willReturn(true); + $redirectResponse1->getHeaderLine('Location')->willReturn('/redirect'); + + $redirectResponse2->getStatusCode()->willReturn(302); + $redirectResponse2->hasHeader('Location')->willReturn(true); + $redirectResponse2->getHeaderLine('Location')->willReturn('/original'); + + $next = function (RequestInterface $currentRequest) use ($request, $redirectResponse1, $redirectResponse2): Promise { + return ($currentRequest === $request->getWrappedObject()) + ? new HttpFulfilledPromise($redirectResponse1->getWrappedObject()) + : new HttpFulfilledPromise($redirectResponse2->getWrappedObject()) + ; + }; + + $redirectPlugin = $this; + $firstCalled = false; + $first = function (RequestInterface $request) use (&$firstCalled, $redirectPlugin, $next, &$first) { + if ($firstCalled) { + throw new \Exception('only one redirect expected'); } + $firstCalled = true; + + return $redirectPlugin->getWrappedObject()->handleRequest($request, $next, $first); }; + $request->getUri()->willReturn($uri); + $uri->__toString()->willReturn('/original'); + + $modifiedRequest->getUri()->willReturn($redirectUri); + $redirectUri->__toString()->willReturn('/redirect'); + + $uri->withPath('/redirect')->willReturn($redirectUri); + $redirectUri->withFragment('')->willReturn($redirectUri); + $redirectUri->withQuery('')->willReturn($redirectUri); + + $redirectUri->withPath('/original')->willReturn($uri); + $uri->withFragment('')->willReturn($uri); + $uri->withQuery('')->willReturn($uri); + + $request->withUri($redirectUri)->willReturn($modifiedRequest); + $request->getMethod()->willReturn('GET'); + $modifiedRequest->withUri($uri)->willReturn($request); + $modifiedRequest->getMethod()->willReturn('GET'); + $promise = $this->handleRequest($request, $next, $first); $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); $promise->shouldThrow(CircularRedirectionException::class)->duringWait(); @@ -440,33 +506,3 @@ public function it_redirects_http_to_https( $finalPromise->wait()->shouldReturn($finalResponse); } } - -class RedirectPluginStub extends RedirectPlugin -{ - public function __construct(UriInterface $uri, $storedUrl, $status, array $config = []) - { - parent::__construct($config); - - $this->redirectStorage[$storedUrl] = [ - 'uri' => $uri, - 'status' => $status, - ]; - } - - public function hasStorage($url) - { - return isset($this->redirectStorage[$url]); - } -} - -class RedirectPluginStubCircular extends RedirectPlugin -{ - public function __construct($chainHash) - { - $this->circularDetection = [ - $chainHash => [ - '/redirect', - ], - ]; - } -} diff --git a/src/Plugin/RedirectPlugin.php b/src/Plugin/RedirectPlugin.php index 80c5251..89b0f39 100644 --- a/src/Plugin/RedirectPlugin.php +++ b/src/Plugin/RedirectPlugin.php @@ -18,14 +18,14 @@ * * @author Joel Wurtz */ -class RedirectPlugin implements Plugin +final class RedirectPlugin implements Plugin { /** * Rule on how to redirect, change method for the new request. * * @var array */ - protected $redirectCodes = [ + private $redirectCodes = [ 300 => [ 'switch' => [ 'unless' => ['GET', 'HEAD'], @@ -79,26 +79,26 @@ class RedirectPlugin implements Plugin * false will ditch all previous headers * string[] will keep only headers with the specified names */ - protected $preserveHeader; + private $preserveHeader; /** * Store all previous redirect from 301 / 308 status code. * * @var array */ - protected $redirectStorage = []; + private $redirectStorage = []; /** * Whether the location header must be directly used for a multiple redirection status code (300). * * @var bool */ - protected $useDefaultForMultiple; + private $useDefaultForMultiple; /** * @var array */ - protected $circularDetection = []; + private $circularDetection = []; /** * @param array $config { @@ -143,7 +143,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl return $first($redirectRequest); } - return $next($request)->then(function (ResponseInterface $response) use ($request, $first) { + return $next($request)->then(function (ResponseInterface $response) use ($request, $first): ResponseInterface { $statusCode = $response->getStatusCode(); if (!array_key_exists($statusCode, $this->redirectCodes)) { @@ -171,7 +171,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl ]; } - // Call redirect request in synchrone + // Call redirect request synchronously $redirectPromise = $first($redirectRequest); return $redirectPromise->wait(); @@ -187,7 +187,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl * * @return MessageInterface|RequestInterface */ - protected function buildRedirectRequest(RequestInterface $request, UriInterface $uri, $statusCode) + private function buildRedirectRequest(RequestInterface $request, UriInterface $uri, $statusCode) { $request = $request->withUri($uri); From 18e36cccd8e000b6afb21d9e2593da10bedc5e21 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Sun, 9 Dec 2018 12:09:33 +0100 Subject: [PATCH 14/28] adjust decider to not retry client errors (#125) --- CHANGELOG.md | 1 + spec/Plugin/RetryPluginSpec.php | 22 ++++++++++++++++++++++ src/Plugin/RetryPlugin.php | 6 ++++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6a01d9..ac296f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 2.0 (unreleased) ### Changed +- RetryPlugin will no longer retry requests when the response failed with a HTTP code < 500. - Abstract method `HttpClientPool::chooseHttpClient()` has now an explicit return type (`Http\Client\Common\HttpClientPoolItem`) - Interface method `Plugin::handleRequest(...)` has now an explicit return type (`Http\Promise\Promise`) diff --git a/spec/Plugin/RetryPluginSpec.php b/spec/Plugin/RetryPluginSpec.php index 682b892..1ffb70a 100644 --- a/spec/Plugin/RetryPluginSpec.php +++ b/spec/Plugin/RetryPluginSpec.php @@ -59,6 +59,28 @@ public function it_throws_exception_on_multiple_exceptions(RequestInterface $req $promise->shouldThrow($exception2)->duringWait(); } + public function it_does_not_retry_client_errors(RequestInterface $request, ResponseInterface $response) + { + $exception = new Exception\HttpException('Exception', $request->getWrappedObject(), $response->getWrappedObject()); + + $seen = false; + $next = function (RequestInterface $receivedRequest) use ($request, $exception, &$seen) { + if (!Argument::is($request->getWrappedObject())->scoreArgument($receivedRequest)) { + throw new \Exception('Unexpected request received'); + } + if ($seen) { + throw new \Exception('This should only be called once'); + } + $seen = true; + + return new HttpRejectedPromise($exception); + }; + + $promise = $this->handleRequest($request, $next, function () {}); + $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class); + $promise->shouldThrow($exception)->duringWait(); + } + public function it_returns_response_on_second_try(RequestInterface $request, ResponseInterface $response) { $exception = new Exception\NetworkException('Exception 1', $request->getWrappedObject()); diff --git a/src/Plugin/RetryPlugin.php b/src/Plugin/RetryPlugin.php index c10bce4..a0da75c 100644 --- a/src/Plugin/RetryPlugin.php +++ b/src/Plugin/RetryPlugin.php @@ -4,6 +4,7 @@ use Http\Client\Common\Plugin; use Http\Client\Exception; +use Http\Client\Exception\HttpException; use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -56,7 +57,8 @@ public function __construct(array $config = []) $resolver->setDefaults([ 'retries' => 1, 'decider' => function (RequestInterface $request, Exception $e) { - return true; + // do not retry client errors + return !$e instanceof HttpException || $e->getCode() >= 500; }, 'delay' => __CLASS__.'::defaultDelay', ]); @@ -101,7 +103,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $time = call_user_func($this->delay, $request, $exception, $this->retryStorage[$chainIdentifier]); usleep($time); - // Retry in synchrone + // Retry synchronously ++$this->retryStorage[$chainIdentifier]; $promise = $this->handleRequest($request, $next, $first); From 5541efdc6288a40ef1897af6ceef8371137beb92 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Sat, 15 Dec 2018 11:28:33 +0100 Subject: [PATCH 15/28] fix AddPathPluginSpec for strict return types --- spec/Plugin/AddPathPluginSpec.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/Plugin/AddPathPluginSpec.php b/spec/Plugin/AddPathPluginSpec.php index b2a6cae..414fa04 100644 --- a/spec/Plugin/AddPathPluginSpec.php +++ b/spec/Plugin/AddPathPluginSpec.php @@ -63,7 +63,7 @@ function it_removes_ending_slashes( $uri->getPath()->shouldBeCalled()->willReturn('/users'); $this->beConstructedWith($host); - $this->handleRequest($request, function () {}, function () {}); + $this->handleRequest($request, PluginStub::next(), function () {}); } public function it_throws_exception_on_empty_path(UriInterface $host) From fadb51abcecdcb0d24ffc2b539f31f030dae1d20 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Sun, 2 Dec 2018 09:11:06 +0100 Subject: [PATCH 16/28] mark classes as final and methods and properties as private We add interfaces for final classes so that they can be mocked in testing. We chose to use the Interface suffix here to avoid name clashes, rather than renaming the existing PHP classes. The interfaces are only relevant for unit testing, we do not expect people to provide their own implementations. HttpClientPoolItem is purely internal and we therefore don't want an interface for it. It is marked with @final and explained to not be meant to extend. --- CHANGELOG.md | 4 + .../HttpClientPoolItemSpec.php | 2 +- .../LeastUsedClientPoolSpec.php | 2 +- spec/HttpClientPool/RandomClientPoolSpec.php | 2 +- .../RoundRobinClientPoolSpec.php | 2 +- spec/HttpClientRouterSpec.php | 8 +- spec/HttpMethodsClientSpec.php | 123 ++++++------------ spec/Plugin/AddPathPluginSpec.php | 2 +- src/BatchClient.php | 26 +--- src/BatchClientInterface.php | 34 +++++ src/Deferred.php | 2 +- src/EmulatedHttpAsyncClient.php | 6 +- src/EmulatedHttpClient.php | 6 +- src/HttpClientPool.php | 45 +------ src/HttpClientPool/HttpClientPool.php | 61 +++++++++ .../HttpClientPoolItem.php | 57 ++++---- src/HttpClientPool/LeastUsedClientPool.php | 2 - src/HttpClientPool/RandomClientPool.php | 2 - src/HttpClientPool/RoundRobinClientPool.php | 2 - src/HttpClientRouter.php | 12 +- src/HttpClientRouterInterface.php | 24 ++++ src/HttpMethodsClient.php | 94 +------------ src/HttpMethodsClientInterface.php | 114 ++++++++++++++++ 23 files changed, 326 insertions(+), 306 deletions(-) rename spec/{ => HttpClientPool}/HttpClientPoolItemSpec.php (99%) create mode 100644 src/BatchClientInterface.php create mode 100644 src/HttpClientPool/HttpClientPool.php rename src/{ => HttpClientPool}/HttpClientPoolItem.php (73%) create mode 100644 src/HttpClientRouterInterface.php create mode 100644 src/HttpMethodsClientInterface.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cbc9e0..f115d39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ - RetryPlugin will no longer retry requests when the response failed with a HTTP code < 500. - Abstract method `HttpClientPool::chooseHttpClient()` has now an explicit return type (`Http\Client\Common\HttpClientPoolItem`) - Interface method `Plugin::handleRequest(...)` has now an explicit return type (`Http\Promise\Promise`) +- Made classes final that are not intended to be extended. + Added interfaces for BatchClient, HttpClientRouter and HttpMethodsClient. + (These interfaces use the `Interface` suffix to avoid name collisions.) +- Added an interface for HttpClientPool and moved the abstract class to the HttpClientPool sub namespace. ### Removed - Deprecated option `debug_plugins` has been removed from `PluginClient` diff --git a/spec/HttpClientPoolItemSpec.php b/spec/HttpClientPool/HttpClientPoolItemSpec.php similarity index 99% rename from spec/HttpClientPoolItemSpec.php rename to spec/HttpClientPool/HttpClientPoolItemSpec.php index f44351b..22c0b7d 100644 --- a/spec/HttpClientPoolItemSpec.php +++ b/spec/HttpClientPool/HttpClientPoolItemSpec.php @@ -1,6 +1,6 @@ shouldHaveType(HttpClientRouter::class); } + public function it_is_an_http_client_router() + { + $this->shouldImplement(HttpClientRouterInterface::class); + } + public function it_is_an_http_client() { $this->shouldImplement(HttpClient::class); diff --git a/spec/HttpMethodsClientSpec.php b/spec/HttpMethodsClientSpec.php index 74e0810..68e124d 100644 --- a/spec/HttpMethodsClientSpec.php +++ b/spec/HttpMethodsClientSpec.php @@ -2,135 +2,88 @@ namespace spec\Http\Client\Common; -use GuzzleHttp\Psr7\Response; use Http\Client\Common\HttpMethodsClient; use Http\Client\HttpClient; -use Http\Message\MessageFactory; +use Http\Message\RequestFactory; use PhpSpec\ObjectBehavior; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; class HttpMethodsClientSpec extends ObjectBehavior { - public function let(HttpClient $client, MessageFactory $messageFactory) + private static $requestData = [ + 'uri' => '/uri', + 'headers' => [ + 'Content-Type' => 'text/plain', + ], + 'body' => 'body', + ]; + + public function let(HttpClient $client, RequestFactory $requestFactory) { $this->beAnInstanceOf( - HttpMethodsClientStub::class, [ + HttpMethodsClient::class, [ $client, - $messageFactory, + $requestFactory, ] ); } - public function it_sends_a_get_request() + public function it_sends_a_get_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) { - $data = HttpMethodsClientStub::$requestData; - - $this->get($data['uri'], $data['headers'])->shouldReturnAnInstanceOf(ResponseInterface::class); + $this->assert($client, $requestFactory, $request, $response, 'get'); } - public function it_sends_a_head_request() + public function it_sends_a_head_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) { - $data = HttpMethodsClientStub::$requestData; - - $this->head($data['uri'], $data['headers'])->shouldReturnAnInstanceOf(ResponseInterface::class); + $this->assert($client, $requestFactory, $request, $response, 'head'); } - public function it_sends_a_trace_request() + public function it_sends_a_trace_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) { - $data = HttpMethodsClientStub::$requestData; - - $this->trace($data['uri'], $data['headers'])->shouldReturnAnInstanceOf(ResponseInterface::class); + $this->assert($client, $requestFactory, $request, $response, 'trace'); } - public function it_sends_a_post_request() + public function it_sends_a_post_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) { - $data = HttpMethodsClientStub::$requestData; - - $this->post($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); + $this->assert($client, $requestFactory, $request, $response, 'post', self::$requestData['body']); } - public function it_sends_a_put_request() + public function it_sends_a_put_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) { - $data = HttpMethodsClientStub::$requestData; - - $this->put($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); + $this->assert($client, $requestFactory, $request, $response, 'put', self::$requestData['body']); } - public function it_sends_a_patch_request() + public function it_sends_a_patch_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) { - $data = HttpMethodsClientStub::$requestData; - - $this->patch($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); + $this->assert($client, $requestFactory, $request, $response, 'patch', self::$requestData['body']); } - public function it_sends_a_delete_request() + public function it_sends_a_delete_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) { - $data = HttpMethodsClientStub::$requestData; - - $this->delete($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); + $this->assert($client, $requestFactory, $request, $response, 'delete', self::$requestData['body']); } - public function it_sends_a_options_request() + public function it_sends_an_options_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) { - $data = HttpMethodsClientStub::$requestData; - - $this->options($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); + $this->assert($client, $requestFactory, $request, $response, 'options', self::$requestData['body']); } - public function it_sends_request_with_underlying_client(HttpClient $client, MessageFactory $messageFactory, RequestInterface $request, ResponseInterface $response) + /** + * Run the actual test. + * + * As there is no data provider in phpspec, we keep separate methods to get new mocks for each test. + */ + private function assert(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response, string $method, string $body = null) { $client->sendRequest($request)->shouldBeCalled()->willReturn($response); + $this->mockFactory($requestFactory, $request, strtoupper($method), $body); - $this->beConstructedWith($client, $messageFactory); - $this->sendRequest($request)->shouldReturn($response); + $this->$method(self::$requestData['uri'], self::$requestData['headers'], self::$requestData['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); } -} - -class HttpMethodsClientStub extends HttpMethodsClient -{ - public static $requestData = [ - 'uri' => '/uri', - 'headers' => [ - 'Content-Type' => 'text/plain', - ], - 'body' => 'body', - ]; - /** - * {@inheritdoc} - */ - public function send($method, $uri, array $headers = [], $body = null): ResponseInterface + private function mockFactory(RequestFactory $requestFactory, RequestInterface $request, string $method, string $body = null) { - if ($uri !== self::$requestData['uri']) { - throw new \InvalidArgumentException('Invalid URI: '.$uri); - } - - if ($headers !== self::$requestData['headers']) { - throw new \InvalidArgumentException('Invalid headers: '.print_r($headers, true)); - } - - switch ($method) { - case 'GET': - case 'HEAD': - case 'TRACE': - if (null !== $body) { - throw new \InvalidArgumentException('Non-empty body'); - } - - return new Response(); - case 'POST': - case 'PUT': - case 'PATCH': - case 'DELETE': - case 'OPTIONS': - if ($body !== self::$requestData['body']) { - throw new \InvalidArgumentException('Invalid body: '.print_r($body, true)); - } - - return new Response(); - default: - throw new \InvalidArgumentException('Invalid method: '.$method); - } + $requestFactory->createRequest($method, self::$requestData['uri'], self::$requestData['headers'], $body)->willReturn($request); } } diff --git a/spec/Plugin/AddPathPluginSpec.php b/spec/Plugin/AddPathPluginSpec.php index 414fa04..6491069 100644 --- a/spec/Plugin/AddPathPluginSpec.php +++ b/spec/Plugin/AddPathPluginSpec.php @@ -46,7 +46,7 @@ public function it_adds_path( $this->handleRequest($request, PluginStub::next(), function () {}); } - function it_removes_ending_slashes( + public function it_removes_ending_slashes( RequestInterface $request, UriInterface $host, UriInterface $host2, diff --git a/src/BatchClient.php b/src/BatchClient.php index 8dfeb81..09a83ff 100644 --- a/src/BatchClient.php +++ b/src/BatchClient.php @@ -8,14 +8,7 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; -/** - * BatchClient allow to sends multiple request and retrieve a Batch Result. - * - * This implementation simply loops over the requests and uses sendRequest with each of them. - * - * @author Joel Wurtz - */ -class BatchClient implements HttpClient +final class BatchClient implements BatchClientInterface { /** * @var HttpClient @@ -27,28 +20,11 @@ public function __construct(HttpClient $client) $this->client = $client; } - /** - * {@inheritdoc} - */ public function sendRequest(RequestInterface $request): ResponseInterface { return $this->client->sendRequest($request); } - /** - * Send several requests. - * - * You may not assume that the requests are executed in a particular order. If the order matters - * for your application, use sendRequest sequentially. - * - * @param RequestInterface[] The requests to send - * - * @return BatchResult Containing one result per request - * - * @throws BatchException If one or more requests fails. The exception gives access to the - * BatchResult with a map of request to result for success, request to - * exception for failures - */ public function sendRequests(array $requests): BatchResult { $batchResult = new BatchResult(); diff --git a/src/BatchClientInterface.php b/src/BatchClientInterface.php new file mode 100644 index 0000000..ce6c3c7 --- /dev/null +++ b/src/BatchClientInterface.php @@ -0,0 +1,34 @@ + + */ +interface BatchClientInterface extends HttpClient +{ + /** + * Send several requests. + * + * You may not assume that the requests are executed in a particular order. If the order matters + * for your application, use sendRequest sequentially. + * + * @param RequestInterface[] The requests to send + * + * @return BatchResult Containing one result per request + * + * @throws BatchException If one or more requests fails. The exception gives access to the + * BatchResult with a map of request to result for success, request to + * exception for failures + */ + public function sendRequests(array $requests): BatchResult; +} diff --git a/src/Deferred.php b/src/Deferred.php index 7413451..c294a8d 100644 --- a/src/Deferred.php +++ b/src/Deferred.php @@ -9,7 +9,7 @@ /** * A deferred allow to return a promise which has not been resolved yet. */ -class Deferred implements Promise +final class Deferred implements Promise { private $value; diff --git a/src/EmulatedHttpAsyncClient.php b/src/EmulatedHttpAsyncClient.php index 64acd59..9d6c557 100644 --- a/src/EmulatedHttpAsyncClient.php +++ b/src/EmulatedHttpAsyncClient.php @@ -6,13 +6,11 @@ use Http\Client\HttpClient; /** - * Emulates an async HTTP client. - * - * This should be replaced by an anonymous class in PHP 7. + * Emulates an async HTTP client with the help of a synchronous client. * * @author Márk Sági-Kazár */ -class EmulatedHttpAsyncClient implements HttpClient, HttpAsyncClient +final class EmulatedHttpAsyncClient implements HttpClient, HttpAsyncClient { use HttpAsyncClientEmulator; use HttpClientDecorator; diff --git a/src/EmulatedHttpClient.php b/src/EmulatedHttpClient.php index 3635e9f..d99b4e4 100644 --- a/src/EmulatedHttpClient.php +++ b/src/EmulatedHttpClient.php @@ -6,13 +6,11 @@ use Http\Client\HttpClient; /** - * Emulates an HTTP client. - * - * This should be replaced by an anonymous class in PHP 7. + * Emulates a synchronous HTTP client with the help of an asynchronous client. * * @author Márk Sági-Kazár */ -class EmulatedHttpClient implements HttpClient, HttpAsyncClient +final class EmulatedHttpClient implements HttpClient, HttpAsyncClient { use HttpAsyncClientDecorator; use HttpClientEmulator; diff --git a/src/HttpClientPool.php b/src/HttpClientPool.php index 90a8464..a730f50 100644 --- a/src/HttpClientPool.php +++ b/src/HttpClientPool.php @@ -2,59 +2,20 @@ namespace Http\Client\Common; -use Http\Client\Common\Exception\HttpClientNotFoundException; +use Http\Client\Common\HttpClientPool\HttpClientPoolItem; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; /** * A http client pool allows to send requests on a pool of different http client using a specific strategy (least used, * round robin, ...). */ -abstract class HttpClientPool implements HttpAsyncClient, HttpClient +interface HttpClientPool extends HttpAsyncClient, HttpClient { - /** - * @var HttpClientPoolItem[] - */ - protected $clientPool = []; - /** * Add a client to the pool. * * @param HttpClient|HttpAsyncClient|HttpClientPoolItem $client */ - public function addHttpClient($client) - { - if (!$client instanceof HttpClientPoolItem) { - $client = new HttpClientPoolItem($client); - } - - $this->clientPool[] = $client; - } - - /** - * Return an http client given a specific strategy. - * - * @throws HttpClientNotFoundException When no http client has been found into the pool - * - * @return HttpClientPoolItem Return a http client that can do both sync or async - */ - abstract protected function chooseHttpClient(): HttpClientPoolItem; - - /** - * {@inheritdoc} - */ - public function sendAsyncRequest(RequestInterface $request) - { - return $this->chooseHttpClient()->sendAsyncRequest($request); - } - - /** - * {@inheritdoc} - */ - public function sendRequest(RequestInterface $request): ResponseInterface - { - return $this->chooseHttpClient()->sendRequest($request); - } + public function addHttpClient($client); } diff --git a/src/HttpClientPool/HttpClientPool.php b/src/HttpClientPool/HttpClientPool.php new file mode 100644 index 0000000..cbac805 --- /dev/null +++ b/src/HttpClientPool/HttpClientPool.php @@ -0,0 +1,61 @@ +clientPool[] = $client; + } + + /** + * Return an http client given a specific strategy. + * + * @throws HttpClientNotFoundException When no http client has been found into the pool + * + * @return HttpClientPoolItem Return a http client that can do both sync or async + */ + abstract protected function chooseHttpClient(): HttpClientPoolItem; + + /** + * {@inheritdoc} + */ + public function sendAsyncRequest(RequestInterface $request) + { + return $this->chooseHttpClient()->sendAsyncRequest($request); + } + + /** + * {@inheritdoc} + */ + public function sendRequest(RequestInterface $request): ResponseInterface + { + return $this->chooseHttpClient()->sendRequest($request); + } +} diff --git a/src/HttpClientPoolItem.php b/src/HttpClientPool/HttpClientPoolItem.php similarity index 73% rename from src/HttpClientPoolItem.php rename to src/HttpClientPool/HttpClientPoolItem.php index a46ee2f..4094502 100644 --- a/src/HttpClientPoolItem.php +++ b/src/HttpClientPool/HttpClientPoolItem.php @@ -1,7 +1,8 @@ */ @@ -29,7 +37,11 @@ class HttpClientPoolItem implements HttpClient, HttpAsyncClient private $disabledAt; /** - * @var int|null Number of seconds after this client is reenable, by default null: never reenable this client + * Number of seconds until this client is enabled again after an error. + * + * null: never reenable this client. + * + * @var int|null */ private $reenableAfter; @@ -40,7 +52,7 @@ class HttpClientPoolItem implements HttpClient, HttpAsyncClient /** * @param HttpClient|HttpAsyncClient $client - * @param null|int $reenableAfter Number of seconds after this client is reenable + * @param null|int $reenableAfter Number of seconds until this client is enabled again after an error */ public function __construct($client, $reenableAfter = null) { @@ -97,21 +109,16 @@ public function sendAsyncRequest(RequestInterface $request) /** * Whether this client is disabled or not. * - * Will also reactivate this client if possible - * - * @internal - * - * @return bool + * If the client was disabled, calling this method checks if the client can + * be reenabled and if so enables it. */ - public function isDisabled() + public function isDisabled(): bool { - $disabledAt = $this->getDisabledAt(); - - if (null !== $this->reenableAfter && null !== $disabledAt) { + if (null !== $this->reenableAfter && null !== $this->disabledAt) { // Reenable after a certain time $now = new \DateTime(); - if (($now->getTimestamp() - $disabledAt->getTimestamp()) >= $this->reenableAfter) { + if (($now->getTimestamp() - $this->disabledAt->getTimestamp()) >= $this->reenableAfter) { $this->enable(); return false; @@ -120,31 +127,17 @@ public function isDisabled() return true; } - return null !== $disabledAt; + return null !== $this->disabledAt; } /** - * Get current number of request that is send by the underlying http client. - * - * @internal - * - * @return int + * Get current number of request that are currently being sent by the underlying HTTP client. */ - public function getSendingRequestCount() + public function getSendingRequestCount(): int { return $this->sendingRequestCount; } - /** - * Return when this client has been disabled or null if it's enabled. - * - * @return \DateTime|null - */ - private function getDisabledAt() - { - return $this->disabledAt; - } - /** * Increment the request count. */ diff --git a/src/HttpClientPool/LeastUsedClientPool.php b/src/HttpClientPool/LeastUsedClientPool.php index 61eb670..e3c29b7 100644 --- a/src/HttpClientPool/LeastUsedClientPool.php +++ b/src/HttpClientPool/LeastUsedClientPool.php @@ -3,8 +3,6 @@ namespace Http\Client\Common\HttpClientPool; use Http\Client\Common\Exception\HttpClientNotFoundException; -use Http\Client\Common\HttpClientPool; -use Http\Client\Common\HttpClientPoolItem; /** * LeastUsedClientPool will choose the client with the less current request in the pool. diff --git a/src/HttpClientPool/RandomClientPool.php b/src/HttpClientPool/RandomClientPool.php index 2889ed7..3adf5fd 100644 --- a/src/HttpClientPool/RandomClientPool.php +++ b/src/HttpClientPool/RandomClientPool.php @@ -3,8 +3,6 @@ namespace Http\Client\Common\HttpClientPool; use Http\Client\Common\Exception\HttpClientNotFoundException; -use Http\Client\Common\HttpClientPool; -use Http\Client\Common\HttpClientPoolItem; /** * RoundRobinClientPool will choose the next client in the pool. diff --git a/src/HttpClientPool/RoundRobinClientPool.php b/src/HttpClientPool/RoundRobinClientPool.php index 3315b51..13cdf13 100644 --- a/src/HttpClientPool/RoundRobinClientPool.php +++ b/src/HttpClientPool/RoundRobinClientPool.php @@ -3,8 +3,6 @@ namespace Http\Client\Common\HttpClientPool; use Http\Client\Common\Exception\HttpClientNotFoundException; -use Http\Client\Common\HttpClientPool; -use Http\Client\Common\HttpClientPoolItem; /** * RoundRobinClientPool will choose the next client in the pool. diff --git a/src/HttpClientRouter.php b/src/HttpClientRouter.php index 00ca15f..56be0bf 100644 --- a/src/HttpClientRouter.php +++ b/src/HttpClientRouter.php @@ -10,11 +10,11 @@ use Psr\Http\Message\ResponseInterface; /** - * Route a request to a specific client in the stack based using a RequestMatcher. + * {@inheritdoc} * * @author Joel Wurtz */ -final class HttpClientRouter implements HttpClient, HttpAsyncClient +final class HttpClientRouter implements HttpClientRouterInterface { /** * @var array @@ -26,9 +26,7 @@ final class HttpClientRouter implements HttpClient, HttpAsyncClient */ public function sendRequest(RequestInterface $request): ResponseInterface { - $client = $this->chooseHttpClient($request); - - return $client->sendRequest($request); + return $this->chooseHttpClient($request)->sendRequest($request); } /** @@ -36,9 +34,7 @@ public function sendRequest(RequestInterface $request): ResponseInterface */ public function sendAsyncRequest(RequestInterface $request) { - $client = $this->chooseHttpClient($request); - - return $client->sendAsyncRequest($request); + return $this->chooseHttpClient($request)->sendAsyncRequest($request); } /** diff --git a/src/HttpClientRouterInterface.php b/src/HttpClientRouterInterface.php new file mode 100644 index 0000000..67fb822 --- /dev/null +++ b/src/HttpClientRouterInterface.php @@ -0,0 +1,24 @@ + + */ +interface HttpClientRouterInterface extends HttpClient, HttpAsyncClient +{ + /** + * Add a client to the router. + * + * @param HttpClient|HttpAsyncClient $client + */ + public function addClient($client, RequestMatcher $requestMatcher); +} diff --git a/src/HttpMethodsClient.php b/src/HttpMethodsClient.php index bc02ef8..69e4df9 100644 --- a/src/HttpMethodsClient.php +++ b/src/HttpMethodsClient.php @@ -2,29 +2,12 @@ namespace Http\Client\Common; -use Http\Client\Exception; use Http\Client\HttpClient; use Http\Message\RequestFactory; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; -use Psr\Http\Message\UriInterface; -/** - * Convenience HTTP client that integrates the MessageFactory in order to send - * requests in the following form:. - * - * $client - * ->get('/foo') - * ->post('/bar') - * ; - * - * The client also exposes the sendRequest methods of the wrapped HttpClient. - * - * @author Márk Sági-Kazár - * @author David Buchmann - */ -class HttpMethodsClient implements HttpClient +final class HttpMethodsClient implements HttpMethodsClientInterface { /** * @var HttpClient @@ -46,116 +29,46 @@ public function __construct(HttpClient $httpClient, RequestFactory $requestFacto $this->requestFactory = $requestFactory; } - /** - * Sends a GET request. - * - * @param string|UriInterface $uri - * - * @throws Exception - */ public function get($uri, array $headers = []): ResponseInterface { return $this->send('GET', $uri, $headers, null); } - /** - * Sends an HEAD request. - * - * @param string|UriInterface $uri - * - * @throws Exception - */ public function head($uri, array $headers = []): ResponseInterface { return $this->send('HEAD', $uri, $headers, null); } - /** - * Sends a TRACE request. - * - * @param string|UriInterface $uri - * - * @throws Exception - */ public function trace($uri, array $headers = []): ResponseInterface { return $this->send('TRACE', $uri, $headers, null); } - /** - * Sends a POST request. - * - * @param string|UriInterface $uri - * @param string|StreamInterface|null $body - * - * @throws Exception - */ public function post($uri, array $headers = [], $body = null): ResponseInterface { return $this->send('POST', $uri, $headers, $body); } - /** - * Sends a PUT request. - * - * @param string|UriInterface $uri - * @param string|StreamInterface|null $body - * - * @throws Exception - */ public function put($uri, array $headers = [], $body = null): ResponseInterface { return $this->send('PUT', $uri, $headers, $body); } - /** - * Sends a PATCH request. - * - * @param string|UriInterface $uri - * @param string|StreamInterface|null $body - * - * @throws Exception - */ public function patch($uri, array $headers = [], $body = null): ResponseInterface { return $this->send('PATCH', $uri, $headers, $body); } - /** - * Sends a DELETE request. - * - * @param string|UriInterface $uri - * @param string|StreamInterface|null $body - * - * @throws Exception - */ public function delete($uri, array $headers = [], $body = null): ResponseInterface { return $this->send('DELETE', $uri, $headers, $body); } - /** - * Sends an OPTIONS request. - * - * @param string|UriInterface $uri - * @param string|StreamInterface|null $body - * - * @throws Exception - */ public function options($uri, array $headers = [], $body = null): ResponseInterface { return $this->send('OPTIONS', $uri, $headers, $body); } - /** - * Sends a request with any HTTP method. - * - * @param string $method HTTP method to use - * @param string|UriInterface $uri - * @param string|StreamInterface|null $body - * - * @throws Exception - */ public function send($method, $uri, array $headers = [], $body = null): ResponseInterface { return $this->sendRequest($this->requestFactory->createRequest( @@ -166,11 +79,6 @@ public function send($method, $uri, array $headers = [], $body = null): Response )); } - /** - * Forward to the underlying HttpClient. - * - * {@inheritdoc} - */ public function sendRequest(RequestInterface $request): ResponseInterface { return $this->httpClient->sendRequest($request); diff --git a/src/HttpMethodsClientInterface.php b/src/HttpMethodsClientInterface.php new file mode 100644 index 0000000..6bc409f --- /dev/null +++ b/src/HttpMethodsClientInterface.php @@ -0,0 +1,114 @@ +get('/foo') + * ->post('/bar') + * ; + * + * The client also exposes the sendRequest methods of the wrapped HttpClient. + * + * @author Márk Sági-Kazár + * @author David Buchmann + */ +interface HttpMethodsClientInterface extends HttpClient +{ + /** + * Sends a GET request. + * + * @param string|UriInterface $uri + * + * @throws Exception + */ + public function get($uri, array $headers = []): ResponseInterface; + + /** + * Sends an HEAD request. + * + * @param string|UriInterface $uri + * + * @throws Exception + */ + public function head($uri, array $headers = []): ResponseInterface; + + /** + * Sends a TRACE request. + * + * @param string|UriInterface $uri + * + * @throws Exception + */ + public function trace($uri, array $headers = []): ResponseInterface; + + /** + * Sends a POST request. + * + * @param string|UriInterface $uri + * @param string|StreamInterface|null $body + * + * @throws Exception + */ + public function post($uri, array $headers = [], $body = null): ResponseInterface; + + /** + * Sends a PUT request. + * + * @param string|UriInterface $uri + * @param string|StreamInterface|null $body + * + * @throws Exception + */ + public function put($uri, array $headers = [], $body = null): ResponseInterface; + + /** + * Sends a PATCH request. + * + * @param string|UriInterface $uri + * @param string|StreamInterface|null $body + * + * @throws Exception + */ + public function patch($uri, array $headers = [], $body = null): ResponseInterface; + + /** + * Sends a DELETE request. + * + * @param string|UriInterface $uri + * @param string|StreamInterface|null $body + * + * @throws Exception + */ + public function delete($uri, array $headers = [], $body = null): ResponseInterface; + + /** + * Sends an OPTIONS request. + * + * @param string|UriInterface $uri + * @param string|StreamInterface|null $body + * + * @throws Exception + */ + public function options($uri, array $headers = [], $body = null): ResponseInterface; + + /** + * Sends a request with any HTTP method. + * + * @param string $method HTTP method to use + * @param string|UriInterface $uri + * @param string|StreamInterface|null $body + * + * @throws Exception + */ + public function send($method, $uri, array $headers = [], $body = null): ResponseInterface; +} From db9afa6af5199af6f0f6fc8cf3b8794235000824 Mon Sep 17 00:00:00 2001 From: Nyholm Date: Wed, 26 Dec 2018 09:42:32 +0100 Subject: [PATCH 17/28] Remove php-cs-fixer from dependencies --- composer.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 0b32bc2..7ada728 100644 --- a/composer.json +++ b/composer.json @@ -22,8 +22,7 @@ "guzzlehttp/psr7": "^1.4", "phpspec/phpspec": "^3.4 || ^4.2", "phpspec/prophecy": ">=1.8", - "sebastian/comparator": ">=2", - "friendsofphp/php-cs-fixer": "^2.2" + "sebastian/comparator": ">=2" }, "suggest": { "php-http/logger-plugin": "PSR-3 Logger plugin", @@ -41,8 +40,6 @@ } }, "scripts": { - "cs-check": "vendor/bin/php-cs-fixer fix --dry-run", - "cs-fix": "vendor/bin/php-cs-fixer fix", "test": "vendor/bin/phpspec run", "test-ci": "vendor/bin/phpspec run -c phpspec.ci.yml" }, From 3e3eed0be5c9ff102a8dce8c92f4e2771996a66b Mon Sep 17 00:00:00 2001 From: Nyholm Date: Wed, 26 Dec 2018 09:40:02 +0100 Subject: [PATCH 18/28] Test on PHP 7.3 --- .travis.yml | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 796c813..84eac28 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,23 +5,14 @@ cache: directories: - $HOME/.composer/cache/files -env: - global: - - TEST_COMMAND="composer test" - -branches: - except: - - /^analysis-.*$/ - php: - 7.0 - 7.1 - 7.2 +- 7.3 matrix: fast_finish: true - allow_failures: - - php: 7.3 jobs: include: @@ -35,19 +26,16 @@ jobs: - wget https://scrutinizer-ci.com/ocular.phar - php ocular.phar code-coverage:upload --format=php-clover build/coverage.xml --revision=$TRAVIS_COMMIT # Test LTS versions - - php: 7.1 + - php: 7.2 env: DEPENDENCIES="dunglas/symfony-lock:^2" - - php: 7.1 + - php: 7.2 env: DEPENDENCIES="dunglas/symfony-lock:^3" - - php: 7.1 - env: DEPENDENCIES="dunglas/symfony-lock:^4" STABILITY="rc" + - php: 7.2 + env: DEPENDENCIES="dunglas/symfony-lock:^4" # Latest dev release - php: 7.3 - sudo: required - before_install: - - composer remove --dev friendsofphp/php-cs-fixer - - env: STABILITY="dev" + env: STABILITY="dev" before_install: - if [[ $COVERAGE != true ]]; then phpenv config-rm xdebug.ini || true; fi From 53bddb2f1a1820c813a35877e8bf8a09d6060d4b Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Sat, 29 Dec 2018 09:52:09 +0100 Subject: [PATCH 19/28] Support PSR-18 (#135) Typecheck for PSR-18 ClientInterface instead of Httplug Client interface. Our interface extends the PSR-18 ClientInterface and therefore is still accepted. No changes for the async client as there is no PSR for that (yet) --- src/BatchClient.php | 6 +++--- src/EmulatedHttpAsyncClient.php | 3 ++- src/FlexibleHttpClient.php | 9 +++++---- src/HttpClientDecorator.php | 6 +++--- src/HttpClientPool.php | 3 ++- src/HttpClientPool/HttpClientPool.php | 4 ++-- src/HttpClientPool/HttpClientPoolItem.php | 5 +++-- src/HttpClientRouter.php | 3 ++- src/HttpClientRouterInterface.php | 3 ++- src/HttpMethodsClient.php | 10 +++++----- src/Plugin/AddPathPlugin.php | 5 ++--- src/PluginClient.php | 11 ++++++----- src/PluginClientFactory.php | 8 ++++---- 13 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/BatchClient.php b/src/BatchClient.php index 09a83ff..b1cbe8d 100644 --- a/src/BatchClient.php +++ b/src/BatchClient.php @@ -3,19 +3,19 @@ namespace Http\Client\Common; use Http\Client\Exception; -use Http\Client\HttpClient; use Http\Client\Common\Exception\BatchException; +use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; final class BatchClient implements BatchClientInterface { /** - * @var HttpClient + * @var ClientInterface */ private $client; - public function __construct(HttpClient $client) + public function __construct(ClientInterface $client) { $this->client = $client; } diff --git a/src/EmulatedHttpAsyncClient.php b/src/EmulatedHttpAsyncClient.php index 9d6c557..d669f25 100644 --- a/src/EmulatedHttpAsyncClient.php +++ b/src/EmulatedHttpAsyncClient.php @@ -4,6 +4,7 @@ use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; +use Psr\Http\Client\ClientInterface; /** * Emulates an async HTTP client with the help of a synchronous client. @@ -15,7 +16,7 @@ final class EmulatedHttpAsyncClient implements HttpClient, HttpAsyncClient use HttpAsyncClientEmulator; use HttpClientDecorator; - public function __construct(HttpClient $httpClient) + public function __construct(ClientInterface $httpClient) { $this->httpClient = $httpClient; } diff --git a/src/FlexibleHttpClient.php b/src/FlexibleHttpClient.php index 58f8813..23d6e9f 100644 --- a/src/FlexibleHttpClient.php +++ b/src/FlexibleHttpClient.php @@ -4,6 +4,7 @@ use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; +use Psr\Http\Client\ClientInterface; /** * A flexible http client, which implements both interface and will emulate @@ -17,18 +18,18 @@ final class FlexibleHttpClient implements HttpClient, HttpAsyncClient use HttpAsyncClientDecorator; /** - * @param HttpClient|HttpAsyncClient $client + * @param ClientInterface|HttpAsyncClient $client */ public function __construct($client) { - if (!($client instanceof HttpClient) && !($client instanceof HttpAsyncClient)) { - throw new \LogicException('Client must be an instance of Http\\Client\\HttpClient or Http\\Client\\HttpAsyncClient'); + if (!($client instanceof ClientInterface) && !($client instanceof HttpAsyncClient)) { + throw new \LogicException('Client must be an instance of Psr\\Http\\Client\\ClientInterface or Http\\Client\\HttpAsyncClient'); } $this->httpClient = $client; $this->httpAsyncClient = $client; - if (!($this->httpClient instanceof HttpClient)) { + if (!($this->httpClient instanceof ClientInterface)) { $this->httpClient = new EmulatedHttpClient($this->httpClient); } diff --git a/src/HttpClientDecorator.php b/src/HttpClientDecorator.php index da5a1bb..9e5724c 100644 --- a/src/HttpClientDecorator.php +++ b/src/HttpClientDecorator.php @@ -2,7 +2,7 @@ namespace Http\Client\Common; -use Http\Client\HttpClient; +use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -14,14 +14,14 @@ trait HttpClientDecorator { /** - * @var HttpClient + * @var ClientInterface */ protected $httpClient; /** * {@inheritdoc} * - * @see HttpClient::sendRequest + * @see ClientInterface::sendRequest */ public function sendRequest(RequestInterface $request): ResponseInterface { diff --git a/src/HttpClientPool.php b/src/HttpClientPool.php index a730f50..c71f9f9 100644 --- a/src/HttpClientPool.php +++ b/src/HttpClientPool.php @@ -5,6 +5,7 @@ use Http\Client\Common\HttpClientPool\HttpClientPoolItem; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; +use Psr\Http\Client\ClientInterface; /** * A http client pool allows to send requests on a pool of different http client using a specific strategy (least used, @@ -15,7 +16,7 @@ interface HttpClientPool extends HttpAsyncClient, HttpClient /** * Add a client to the pool. * - * @param HttpClient|HttpAsyncClient|HttpClientPoolItem $client + * @param ClientInterface|HttpAsyncClient|HttpClientPoolItem $client */ public function addHttpClient($client); } diff --git a/src/HttpClientPool/HttpClientPool.php b/src/HttpClientPool/HttpClientPool.php index cbac805..8e2ce64 100644 --- a/src/HttpClientPool/HttpClientPool.php +++ b/src/HttpClientPool/HttpClientPool.php @@ -5,7 +5,7 @@ use Http\Client\Common\Exception\HttpClientNotFoundException; use Http\Client\Common\HttpClientPool as HttpClientPoolInterface; use Http\Client\HttpAsyncClient; -use Http\Client\HttpClient; +use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -23,7 +23,7 @@ abstract class HttpClientPool implements HttpClientPoolInterface /** * Add a client to the pool. * - * @param HttpClient|HttpAsyncClient|HttpClientPoolItem $client + * @param ClientInterface|HttpAsyncClient|HttpClientPoolItem $client */ public function addHttpClient($client) { diff --git a/src/HttpClientPool/HttpClientPoolItem.php b/src/HttpClientPool/HttpClientPoolItem.php index 4094502..0b382cb 100644 --- a/src/HttpClientPool/HttpClientPoolItem.php +++ b/src/HttpClientPool/HttpClientPoolItem.php @@ -5,6 +5,7 @@ use Http\Client\Common\FlexibleHttpClient; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; +use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Http\Client\Exception; use Psr\Http\Message\ResponseInterface; @@ -51,8 +52,8 @@ class HttpClientPoolItem implements HttpClient, HttpAsyncClient private $client; /** - * @param HttpClient|HttpAsyncClient $client - * @param null|int $reenableAfter Number of seconds until this client is enabled again after an error + * @param ClientInterface|HttpAsyncClient $client + * @param null|int $reenableAfter Number of seconds until this client is enabled again after an error */ public function __construct($client, $reenableAfter = null) { diff --git a/src/HttpClientRouter.php b/src/HttpClientRouter.php index 56be0bf..9008156 100644 --- a/src/HttpClientRouter.php +++ b/src/HttpClientRouter.php @@ -6,6 +6,7 @@ use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; use Http\Message\RequestMatcher; +use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; @@ -53,7 +54,7 @@ public function addClient($client, RequestMatcher $requestMatcher) /** * Choose an HTTP client given a specific request. * - * @return HttpClient|HttpAsyncClient + * @return ClientInterface|HttpAsyncClient */ private function chooseHttpClient(RequestInterface $request) { diff --git a/src/HttpClientRouterInterface.php b/src/HttpClientRouterInterface.php index 67fb822..635e25e 100644 --- a/src/HttpClientRouterInterface.php +++ b/src/HttpClientRouterInterface.php @@ -5,6 +5,7 @@ use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; use Http\Message\RequestMatcher; +use Psr\Http\Client\ClientInterface; /** * Route a request to a specific client in the stack based using a RequestMatcher. @@ -18,7 +19,7 @@ interface HttpClientRouterInterface extends HttpClient, HttpAsyncClient /** * Add a client to the router. * - * @param HttpClient|HttpAsyncClient $client + * @param ClientInterface|HttpAsyncClient $client */ public function addClient($client, RequestMatcher $requestMatcher); } diff --git a/src/HttpMethodsClient.php b/src/HttpMethodsClient.php index 69e4df9..e4ab0f6 100644 --- a/src/HttpMethodsClient.php +++ b/src/HttpMethodsClient.php @@ -2,15 +2,15 @@ namespace Http\Client\Common; -use Http\Client\HttpClient; use Http\Message\RequestFactory; +use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; final class HttpMethodsClient implements HttpMethodsClientInterface { /** - * @var HttpClient + * @var ClientInterface */ private $httpClient; @@ -20,10 +20,10 @@ final class HttpMethodsClient implements HttpMethodsClientInterface private $requestFactory; /** - * @param HttpClient $httpClient The client to send requests with - * @param RequestFactory $requestFactory The message factory to create requests + * @param ClientInterface $httpClient The client to send requests with + * @param RequestFactory $requestFactory The message factory to create requests */ - public function __construct(HttpClient $httpClient, RequestFactory $requestFactory) + public function __construct(ClientInterface $httpClient, RequestFactory $requestFactory) { $this->httpClient = $httpClient; $this->requestFactory = $requestFactory; diff --git a/src/Plugin/AddPathPlugin.php b/src/Plugin/AddPathPlugin.php index 0a2adba..3b7dcaf 100644 --- a/src/Plugin/AddPathPlugin.php +++ b/src/Plugin/AddPathPlugin.php @@ -47,9 +47,8 @@ public function handleRequest(RequestInterface $request, callable $next, callabl $identifier = spl_object_hash((object) $first); if (!array_key_exists($identifier, $this->alteredRequests)) { - $request = $request->withUri($request->getUri() - ->withPath($this->uri->getPath().$request->getUri()->getPath()) - ); + $prefixedUrl = $this->uri->getPath().$request->getUri()->getPath(); + $request = $request->withUri($request->getUri()->withPath($prefixedUrl)); $this->alteredRequests[$identifier] = $identifier; } diff --git a/src/PluginClient.php b/src/PluginClient.php index 264c2fe..4c95300 100644 --- a/src/PluginClient.php +++ b/src/PluginClient.php @@ -8,6 +8,7 @@ use Http\Client\HttpClient; use Http\Client\Promise\HttpFulfilledPromise; use Http\Client\Promise\HttpRejectedPromise; +use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -41,9 +42,9 @@ final class PluginClient implements HttpClient, HttpAsyncClient private $options; /** - * @param HttpClient|HttpAsyncClient $client - * @param Plugin[] $plugins - * @param array $options { + * @param ClientInterface|HttpAsyncClient $client + * @param Plugin[] $plugins + * @param array $options { * * @var int $max_restarts * } @@ -54,10 +55,10 @@ public function __construct($client, array $plugins = [], array $options = []) { if ($client instanceof HttpAsyncClient) { $this->client = $client; - } elseif ($client instanceof HttpClient) { + } elseif ($client instanceof ClientInterface) { $this->client = new EmulatedHttpAsyncClient($client); } else { - throw new \RuntimeException('Client must be an instance of Http\\Client\\HttpClient or Http\\Client\\HttpAsyncClient'); + throw new \RuntimeException('Client must be an instance of Psr\\Http\\Client\\ClientInterface or Http\\Client\\HttpAsyncClient'); } $this->plugins = $plugins; diff --git a/src/PluginClientFactory.php b/src/PluginClientFactory.php index 77642ea..b4a78fc 100644 --- a/src/PluginClientFactory.php +++ b/src/PluginClientFactory.php @@ -3,7 +3,7 @@ namespace Http\Client\Common; use Http\Client\HttpAsyncClient; -use Http\Client\HttpClient; +use Psr\Http\Client\ClientInterface; /** * Factory to create PluginClient instances. Using this factory instead of calling PluginClient constructor will enable @@ -33,9 +33,9 @@ public static function setFactory(callable $factory) } /** - * @param HttpClient|HttpAsyncClient $client - * @param Plugin[] $plugins - * @param array $options { + * @param ClientInterface|HttpAsyncClient $client + * @param Plugin[] $plugins + * @param array $options { * * @var string $client_name to give client a name which may be used when displaying client information like in * the HTTPlugBundle profiler. From 724f0a13f17f2478e3da6a973f8123568e37189d Mon Sep 17 00:00:00 2001 From: Mponos George Date: Sat, 29 Dec 2018 11:33:56 +0200 Subject: [PATCH 20/28] Added declare strict types (#137) --- src/BatchClient.php | 2 ++ src/BatchClientInterface.php | 3 ++- src/BatchResult.php | 2 ++ src/Deferred.php | 2 ++ src/EmulatedHttpAsyncClient.php | 2 ++ src/EmulatedHttpClient.php | 2 ++ src/Exception/BatchException.php | 2 ++ src/Exception/CircularRedirectionException.php | 2 ++ src/Exception/ClientErrorException.php | 2 ++ src/Exception/HttpClientNotFoundException.php | 2 ++ src/Exception/LoopException.php | 2 ++ src/Exception/MultipleRedirectionException.php | 2 ++ src/Exception/ServerErrorException.php | 2 ++ src/FlexibleHttpClient.php | 2 ++ src/HttpAsyncClientDecorator.php | 2 ++ src/HttpAsyncClientEmulator.php | 2 ++ src/HttpClientDecorator.php | 2 ++ src/HttpClientEmulator.php | 2 ++ src/HttpClientPool.php | 2 ++ src/HttpClientPool/HttpClientPool.php | 2 ++ src/HttpClientPool/HttpClientPoolItem.php | 2 ++ src/HttpClientPool/LeastUsedClientPool.php | 2 ++ src/HttpClientPool/RandomClientPool.php | 2 ++ src/HttpClientPool/RoundRobinClientPool.php | 2 ++ src/HttpClientRouter.php | 2 ++ src/HttpClientRouterInterface.php | 2 ++ src/HttpMethodsClient.php | 2 ++ src/HttpMethodsClientInterface.php | 2 ++ src/Plugin.php | 2 ++ src/Plugin/AddHostPlugin.php | 2 ++ src/Plugin/AddPathPlugin.php | 2 ++ src/Plugin/AuthenticationPlugin.php | 2 ++ src/Plugin/BaseUriPlugin.php | 2 ++ src/Plugin/ContentLengthPlugin.php | 2 ++ src/Plugin/ContentTypePlugin.php | 2 ++ src/Plugin/CookiePlugin.php | 4 +++- src/Plugin/DecoderPlugin.php | 2 ++ src/Plugin/ErrorPlugin.php | 2 ++ src/Plugin/HeaderAppendPlugin.php | 2 ++ src/Plugin/HeaderDefaultsPlugin.php | 2 ++ src/Plugin/HeaderRemovePlugin.php | 2 ++ src/Plugin/HeaderSetPlugin.php | 2 ++ src/Plugin/HistoryPlugin.php | 2 ++ src/Plugin/Journal.php | 2 ++ src/Plugin/QueryDefaultsPlugin.php | 2 ++ src/Plugin/RedirectPlugin.php | 2 ++ src/Plugin/RequestMatcherPlugin.php | 2 ++ src/Plugin/RetryPlugin.php | 2 ++ src/Plugin/VersionBridgePlugin.php | 2 ++ src/PluginClient.php | 2 ++ src/PluginClientFactory.php | 2 ++ src/VersionBridgeClient.php | 2 ++ 52 files changed, 105 insertions(+), 2 deletions(-) diff --git a/src/BatchClient.php b/src/BatchClient.php index b1cbe8d..bd340af 100644 --- a/src/BatchClient.php +++ b/src/BatchClient.php @@ -1,5 +1,7 @@ Date: Sat, 29 Dec 2018 11:54:47 +0100 Subject: [PATCH 21/28] Added backwards compatibility layer (#133) --- src/Plugin/VersionBridgePlugin.php | 3 ++- src/VersionBridgeClient.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Plugin/VersionBridgePlugin.php b/src/Plugin/VersionBridgePlugin.php index 45c4364..0a2c714 100644 --- a/src/Plugin/VersionBridgePlugin.php +++ b/src/Plugin/VersionBridgePlugin.php @@ -4,6 +4,7 @@ namespace Http\Client\Common\Plugin; +use Http\Promise\Promise; use Psr\Http\Message\RequestInterface; /** @@ -16,7 +17,7 @@ trait VersionBridgePlugin { abstract protected function doHandleRequest(RequestInterface $request, callable $next, callable $first); - public function handleRequest(RequestInterface $request, callable $next, callable $first) + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { return $this->doHandleRequest($request, $next, $first); } diff --git a/src/VersionBridgeClient.php b/src/VersionBridgeClient.php index f8ab773..a608edd 100644 --- a/src/VersionBridgeClient.php +++ b/src/VersionBridgeClient.php @@ -5,6 +5,7 @@ namespace Http\Client\Common; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; /** * A client that helps you migrate from php-http/httplug 1.x to 2.x. This @@ -16,7 +17,7 @@ trait VersionBridgeClient { abstract protected function doSendRequest(RequestInterface $request); - public function sendRequest(RequestInterface $request) + public function sendRequest(RequestInterface $request): ResponseInterface { return $this->doSendRequest($request); } From 7d5fe4deb07494ddddc49296972de8adfcc59bd6 Mon Sep 17 00:00:00 2001 From: Nyholm Date: Mon, 31 Dec 2018 12:15:51 +0100 Subject: [PATCH 22/28] init --- .travis.yml | 2 ++ phpunit.xml.dist | 14 ++++++++++++++ tests/PluginClientTest.php | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 phpunit.xml.dist create mode 100644 tests/PluginClientTest.php diff --git a/.travis.yml b/.travis.yml index 84eac28..10d366e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,8 @@ jobs: env: DEPENDENCIES="dunglas/symfony-lock:^3" - php: 7.2 env: DEPENDENCIES="dunglas/symfony-lock:^4" + - php: 7.2 + env: TEST_COMMAND="./vendor/bin/phpunit" DEPENDENCIES="phpunit/phpunit:^7.5 nyholm/psr7:^1.0" # Latest dev release - php: 7.3 diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..d353b7c --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,14 @@ + + + + + + + ./tests + + + diff --git a/tests/PluginClientTest.php b/tests/PluginClientTest.php new file mode 100644 index 0000000..d88bbf1 --- /dev/null +++ b/tests/PluginClientTest.php @@ -0,0 +1,18 @@ + Date: Mon, 31 Dec 2018 12:36:17 +0100 Subject: [PATCH 23/28] Small test to prove a bug. --- tests/PluginClientTest.php | 64 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/tests/PluginClientTest.php b/tests/PluginClientTest.php index d88bbf1..47bf8c3 100644 --- a/tests/PluginClientTest.php +++ b/tests/PluginClientTest.php @@ -4,15 +4,73 @@ namespace tests\Http\Client\Common; +use Http\Client\Common\Plugin; +use Http\Client\Common\Plugin\HeaderAppendPlugin; +use Http\Client\Common\Plugin\RedirectPlugin; +use Http\Client\Common\PluginClient; +use Http\Client\HttpAsyncClient; +use Http\Client\Promise\HttpFulfilledPromise; +use Http\Promise\Promise; +use Nyholm\Psr7\Request; +use Nyholm\Psr7\Response; use PHPUnit\Framework\TestCase; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; class PluginClientTest extends TestCase { - private $syncClient; - private $asyncClient; + /** + * @dataProvider clientAndMethodProvider + */ + public function testRestartChain(PluginClient $client, string $method, string $returnType) + { + $request = new Request('GET', 'https://example.com'); + $result = call_user_func([$client, $method], $request); + + $this->assertInstanceOf($returnType, $result); + } - protected function setUp() + public function clientAndMethodProvider() { + $syncClient = new class implements ClientInterface { + public function sendRequest(RequestInterface $request): ResponseInterface + { + return new Response(); + } + }; + + $asyncClient = new class implements HttpAsyncClient { + public function sendAsyncRequest(RequestInterface $request) + { + return new HttpFulfilledPromise(new Response()); + } + }; + + $headerAppendPlugin = new HeaderAppendPlugin(['Content-Type'=>'text/html']); + $redirectPlugin = new RedirectPlugin(); + $restartOncePlugin = new class implements Plugin { + private $firstRun = true; + + public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise + { + if ($this->firstRun) { + $this->firstRun = false; + return $first($request)->wait(); + } + return $next($request); + } + }; + + $plugins = [$headerAppendPlugin, $restartOncePlugin, $redirectPlugin]; + + $pluginClient = new PluginClient($syncClient, $plugins); + yield [$pluginClient, 'sendRequest', ResponseInterface::class]; + yield [$pluginClient, 'sendAsyncRequest', Promise::class]; + // Async + $pluginClient = new PluginClient($asyncClient, $plugins); + yield [$pluginClient, 'sendRequest', ResponseInterface::class]; + yield [$pluginClient, 'sendAsyncRequest', Promise::class]; } } \ No newline at end of file From aea593686d77bcf347d0971dbaf284b32fe6f34e Mon Sep 17 00:00:00 2001 From: Nyholm Date: Mon, 31 Dec 2018 12:43:12 +0100 Subject: [PATCH 24/28] cs --- tests/PluginClientTest.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/PluginClientTest.php b/tests/PluginClientTest.php index 47bf8c3..eb55685 100644 --- a/tests/PluginClientTest.php +++ b/tests/PluginClientTest.php @@ -33,31 +33,34 @@ public function testRestartChain(PluginClient $client, string $method, string $r public function clientAndMethodProvider() { - $syncClient = new class implements ClientInterface { + $syncClient = new class() implements ClientInterface { public function sendRequest(RequestInterface $request): ResponseInterface { return new Response(); } }; - $asyncClient = new class implements HttpAsyncClient { + $asyncClient = new class() implements HttpAsyncClient { public function sendAsyncRequest(RequestInterface $request) { return new HttpFulfilledPromise(new Response()); } }; - $headerAppendPlugin = new HeaderAppendPlugin(['Content-Type'=>'text/html']); + $headerAppendPlugin = new HeaderAppendPlugin(['Content-Type' => 'text/html']); $redirectPlugin = new RedirectPlugin(); - $restartOncePlugin = new class implements Plugin { + $restartOncePlugin = new class() implements Plugin { private $firstRun = true; public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { if ($this->firstRun) { $this->firstRun = false; - return $first($request)->wait(); + + return $first($request); } + $this->firstRun = true; + return $next($request); } }; @@ -73,4 +76,4 @@ public function handleRequest(RequestInterface $request, callable $next, callabl yield [$pluginClient, 'sendRequest', ResponseInterface::class]; yield [$pluginClient, 'sendAsyncRequest', Promise::class]; } -} \ No newline at end of file +} From 7b6cdbed4d3aa55390d2bed24e8af6385e7512a5 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Wed, 2 Jan 2019 09:30:06 +0100 Subject: [PATCH 25/28] fix cs violation introduced when merging master to 2.x --- spec/Plugin/RetryPluginSpec.php | 4 ++-- src/Plugin/RetryPlugin.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/Plugin/RetryPluginSpec.php b/spec/Plugin/RetryPluginSpec.php index 354fc4d..e01ba54 100644 --- a/spec/Plugin/RetryPluginSpec.php +++ b/spec/Plugin/RetryPluginSpec.php @@ -109,12 +109,12 @@ public function it_respects_custom_exception_decider(RequestInterface $request, $this->beConstructedWith([ 'exception_decider' => function (RequestInterface $request, Exception $e) { return false; - } + }, ]); $exception = new Exception\NetworkException('Exception', $request->getWrappedObject()); $called = false; - $next = function (RequestInterface $receivedRequest) use($exception, &$called) { + $next = function (RequestInterface $receivedRequest) use ($exception, &$called) { if ($called) { throw new \RuntimeException('Did not expect to be called multiple times'); } diff --git a/src/Plugin/RetryPlugin.php b/src/Plugin/RetryPlugin.php index d3d372a..5292ddf 100644 --- a/src/Plugin/RetryPlugin.php +++ b/src/Plugin/RetryPlugin.php @@ -48,9 +48,9 @@ final class RetryPlugin implements Plugin /** * @param array $config { * - * @var int $retries Number of retries to attempt if an exception occurs before letting the exception bubble up. - * @var callable $exception_decider A callback that gets a request and an exception to decide after a failure whether the request should be retried. - * @var callable $exception_delay A callback that gets a request, an exception and the number of retries and returns how many microseconds we should wait before trying again. + * @var int $retries Number of retries to attempt if an exception occurs before letting the exception bubble up + * @var callable $exception_decider A callback that gets a request and an exception to decide after a failure whether the request should be retried + * @var callable $exception_delay A callback that gets a request, an exception and the number of retries and returns how many microseconds we should wait before trying again * } */ public function __construct(array $config = []) From 7d80627684224fdc0089f60d39cd8d0f3868c4db Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Wed, 2 Jan 2019 09:25:16 +0100 Subject: [PATCH 26/28] add missing type declarations --- composer.json | 2 ++ src/Plugin/ContentTypePlugin.php | 17 +++++++++-------- src/Plugin/CookiePlugin.php | 12 ++++-------- src/Plugin/DecoderPlugin.php | 17 +++-------------- 4 files changed, 18 insertions(+), 30 deletions(-) diff --git a/composer.json b/composer.json index 8a6e9f4..8701a52 100644 --- a/composer.json +++ b/composer.json @@ -25,6 +25,8 @@ "sebastian/comparator": ">=2" }, "suggest": { + "ext-json": "To detect JSON responses with the ContentTypePlugin", + "ext-libxml": "To detect XML responses with the ContentTypePlugin", "php-http/logger-plugin": "PSR-3 Logger plugin", "php-http/cache-plugin": "PSR-6 Cache plugin", "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" diff --git a/src/Plugin/ContentTypePlugin.php b/src/Plugin/ContentTypePlugin.php index f6dcddd..f3944dd 100644 --- a/src/Plugin/ContentTypePlugin.php +++ b/src/Plugin/ContentTypePlugin.php @@ -94,11 +94,11 @@ public function handleRequest(RequestInterface $request, callable $next, callabl return $next($request); } - /** - * @param $stream StreamInterface - */ - private function isJson($stream): bool + private function isJson(StreamInterface $stream): bool { + if (!function_exists('json_decode')) { + return false; + } $stream->rewind(); json_decode($stream->getContents()); @@ -108,17 +108,18 @@ private function isJson($stream): bool /** * @param $stream StreamInterface - * - * @return \SimpleXMLElement|false */ - private function isXml($stream) + private function isXml(StreamInterface $stream): bool { + if (!function_exists('simplexml_load_string')) { + return false; + } $stream->rewind(); $previousValue = libxml_use_internal_errors(true); $isXml = simplexml_load_string($stream->getContents()); libxml_use_internal_errors($previousValue); - return $isXml; + return false !== $isXml; } } diff --git a/src/Plugin/CookiePlugin.php b/src/Plugin/CookiePlugin.php index 8f8d5b0..8399210 100644 --- a/src/Plugin/CookiePlugin.php +++ b/src/Plugin/CookiePlugin.php @@ -91,15 +91,13 @@ public function handleRequest(RequestInterface $request, callable $next, callabl /** * Creates a cookie from a string. * - * @param $setCookie - * * @return Cookie|null * * @throws TransferException */ - private function createCookie(RequestInterface $request, $setCookie) + private function createCookie(RequestInterface $request, string $setCookieHeader) { - $parts = array_map('trim', explode(';', $setCookie)); + $parts = array_map('trim', explode(';', $setCookieHeader)); if (empty($parts) || !strpos($parts[0], '=')) { return null; @@ -169,11 +167,9 @@ private function createCookie(RequestInterface $request, $setCookie) /** * Separates key/value pair from cookie. * - * @param $part - * - * @return array + * @param string $part A single cookie value in format key=value */ - private function createValueKey($part) + private function createValueKey(string $part): array { $parts = explode('=', $part, 2); $key = trim($parts[0]); diff --git a/src/Plugin/DecoderPlugin.php b/src/Plugin/DecoderPlugin.php index b1ede5d..271ad3c 100644 --- a/src/Plugin/DecoderPlugin.php +++ b/src/Plugin/DecoderPlugin.php @@ -68,12 +68,8 @@ public function handleRequest(RequestInterface $request, callable $next, callabl /** * Decode a response body given its Transfer-Encoding or Content-Encoding value. - * - * @param ResponseInterface $response Response to decode - * - * @return ResponseInterface New response decoded */ - private function decodeResponse(ResponseInterface $response) + private function decodeResponse(ResponseInterface $response): ResponseInterface { $response = $this->decodeOnEncodingHeader('Transfer-Encoding', $response); @@ -86,13 +82,8 @@ private function decodeResponse(ResponseInterface $response) /** * Decode a response on a specific header (content encoding or transfer encoding mainly). - * - * @param string $headerName Name of the header - * @param ResponseInterface $response Response - * - * @return ResponseInterface A new instance of the response decoded */ - private function decodeOnEncodingHeader($headerName, ResponseInterface $response) + private function decodeOnEncodingHeader(string $headerName, ResponseInterface $response): ResponseInterface { if ($response->hasHeader($headerName)) { $encodings = $response->getHeader($headerName); @@ -123,11 +114,9 @@ private function decodeOnEncodingHeader($headerName, ResponseInterface $response /** * Decorate a stream given an encoding. * - * @param string $encoding - * * @return StreamInterface|false A new stream interface or false if encoding is not supported */ - private function decorateStream($encoding, StreamInterface $stream) + private function decorateStream(string $encoding, StreamInterface $stream) { if ('chunked' === strtolower($encoding)) { return new Encoding\DechunkStream($stream); From fc04c8e3e16801e2dc04ecf68f50fd7d76a3bd5e Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Thu, 3 Jan 2019 13:31:32 +0100 Subject: [PATCH 27/28] Dont add path to an url we already added a path to. (#141) --- CHANGELOG.md | 3 +- spec/Plugin/AddPathPluginSpec.php | 4 +- src/Plugin/AddPathPlugin.php | 43 ++++++++++----- tests/Plugin/AddPathPluginTest.php | 85 ++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 tests/Plugin/AddPathPluginTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d028df3..f636a0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Added interfaces for BatchClient, HttpClientRouter and HttpMethodsClient. (These interfaces use the `Interface` suffix to avoid name collisions.) - Added an interface for HttpClientPool and moved the abstract class to the HttpClientPool sub namespace. +- AddPathPlugin: Do not add the prefix if the URL already has the same prefix. ### Removed - Deprecated option `debug_plugins` has been removed from `PluginClient` @@ -18,7 +19,7 @@ ### Changed -- [RetryPlugin] Renamed the configuration options for the exception retry callback from `decider` to `exception_decider` +- RetryPlugin: Renamed the configuration options for the exception retry callback from `decider` to `exception_decider` and `delay` to `exception_delay`. The old names still work but are deprecated. ## 1.8.2 - 2018-12-14 diff --git a/spec/Plugin/AddPathPluginSpec.php b/spec/Plugin/AddPathPluginSpec.php index 6491069..1c6f09d 100644 --- a/spec/Plugin/AddPathPluginSpec.php +++ b/spec/Plugin/AddPathPluginSpec.php @@ -37,9 +37,9 @@ public function it_adds_path( $host->getPath()->shouldBeCalled()->willReturn('/api'); $request->getUri()->shouldBeCalled()->willReturn($uri); - $request->withUri($uri)->shouldBeCalled()->willReturn($request); + $request->withUri($uri)->shouldBeCalledTimes(1)->willReturn($request); - $uri->withPath('/api/users')->shouldBeCalled()->willReturn($uri); + $uri->withPath('/api/users')->shouldBeCalledTimes(1)->willReturn($uri); $uri->getPath()->shouldBeCalled()->willReturn('/users'); $this->beConstructedWith($host); diff --git a/src/Plugin/AddPathPlugin.php b/src/Plugin/AddPathPlugin.php index 8b92514..9d43104 100644 --- a/src/Plugin/AddPathPlugin.php +++ b/src/Plugin/AddPathPlugin.php @@ -21,13 +21,6 @@ final class AddPathPlugin implements Plugin */ private $uri; - /** - * Stores identifiers of the already altered requests. - * - * @var array - */ - private $alteredRequests = []; - public function __construct(UriInterface $uri) { if ('' === $uri->getPath()) { @@ -42,16 +35,42 @@ public function __construct(UriInterface $uri) } /** + * Adds a prefix in the beginning of the URL's path. + * + * The prefix is not added if that prefix is already on the URL's path. This will fail on the edge + * case of the prefix being repeated, for example if `https://example.com/api/api/foo` is a valid + * URL on the server and the configured prefix is `/api`. + * + * We looked at other solutions, but they are all much more complicated, while still having edge + * cases: + * - Doing an spl_object_hash on `$first` will lead to collisions over time because over time the + * hash can collide. + * - Have the PluginClient provide a magic header to identify the request chain and only apply + * this plugin once. + * + * There are 2 reasons for the AddPathPlugin to be executed twice on the same request: + * - A plugin can restart the chain by calling `$first`, e.g. redirect + * - A plugin can call `$next` more than once, e.g. retry + * + * Depending on the scenario, the path should or should not be added. E.g. `$first` could + * be called after a redirect response from the server. The server likely already has the + * correct path. + * + * No solution fits all use cases. This implementation will work fine for the common use cases. + * If you have a specific situation where this is not the right thing, you can build a custom plugin + * that does exactly what you need. + * * {@inheritdoc} */ public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise { - $identifier = spl_object_hash((object) $first); + $prepend = $this->uri->getPath(); + $path = $request->getUri()->getPath(); - if (!array_key_exists($identifier, $this->alteredRequests)) { - $prefixedUrl = $this->uri->getPath().$request->getUri()->getPath(); - $request = $request->withUri($request->getUri()->withPath($prefixedUrl)); - $this->alteredRequests[$identifier] = $identifier; + if (substr($path, 0, strlen($prepend)) !== $prepend) { + $request = $request->withUri($request->getUri() + ->withPath($prepend.$path) + ); } return $next($request); diff --git a/tests/Plugin/AddPathPluginTest.php b/tests/Plugin/AddPathPluginTest.php new file mode 100644 index 0000000..3980fa4 --- /dev/null +++ b/tests/Plugin/AddPathPluginTest.php @@ -0,0 +1,85 @@ +first = function () {}; + $this->plugin = new AddPathPlugin(new Uri('/api')); + } + + public function testRewriteSameUrl() + { + $verify = function (RequestInterface $request) { + $this->assertEquals('https://example.com/api/foo', $request->getUri()->__toString()); + }; + + $request = new Request('GET', 'https://example.com/foo', ['Content-Type'=>'text/html']); + $this->plugin->handleRequest($request, $verify, $this->first); + + // Make a second call with the same $request object + $this->plugin->handleRequest($request, $verify, $this->first); + + // Make a new call with a new object but same URL + $request = new Request('GET', 'https://example.com/foo', ['Content-Type'=>'text/plain']); + $this->plugin->handleRequest($request, $verify, $this->first); + } + + public function testRewriteCallingThePluginTwice() + { + $request = new Request('GET', 'https://example.com/foo'); + $this->plugin->handleRequest($request, function (RequestInterface $request) { + $this->assertEquals('https://example.com/api/foo', $request->getUri()->__toString()); + + // Run the plugin again with the modified request + $this->plugin->handleRequest($request, function (RequestInterface $request) { + $this->assertEquals('https://example.com/api/foo', $request->getUri()->__toString()); + }, $this->first); + }, $this->first); + } + + public function testRewriteWithDifferentUrl() + { + $request = new Request('GET', 'https://example.com/foo'); + $this->plugin->handleRequest($request, function (RequestInterface $request) { + $this->assertEquals('https://example.com/api/foo', $request->getUri()->__toString()); + }, $this->first); + + $request = new Request('GET', 'https://example.com/bar'); + $this->plugin->handleRequest($request, function (RequestInterface $request) { + $this->assertEquals('https://example.com/api/bar', $request->getUri()->__toString()); + }, $this->first); + } + + public function testRewriteWhenPathIsIncluded() + { + $verify = function (RequestInterface $request) { + $this->assertEquals('https://example.com/api/foo', $request->getUri()->__toString()); + }; + + $request = new Request('GET', 'https://example.com/api/foo'); + $this->plugin->handleRequest($request, $verify, $this->first); + } +} From 414cde18d63b6e9587cdb1e01c1efba371f414a5 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Thu, 3 Jan 2019 13:54:48 +0100 Subject: [PATCH 28/28] update composer.json branch alias --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 8701a52..821fe16 100644 --- a/composer.json +++ b/composer.json @@ -47,8 +47,7 @@ }, "extra": { "branch-alias": { - "dev-2.x": "2.x-dev", - "dev-master": "1.9.x-dev" + "dev-master": "2.x-dev" } } }