diff --git a/.gitignore b/.gitignore
index 16b4a20..8ce13f3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+/.php_cs
+/.php_cs.cache
/behat.yml
/build/
/composer.lock
diff --git a/.php_cs b/.php_cs
deleted file mode 100644
index 23ba165..0000000
--- a/.php_cs
+++ /dev/null
@@ -1,13 +0,0 @@
-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);
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
diff --git a/.travis.yml b/.travis.yml
index 6af5f34..10d366e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,67 +1,55 @@
language: php
-
sudo: false
-dist: trusty
-
cache:
- directories:
- - $HOME/.composer/cache/files
+ 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
- include:
- - php: 7.1
- env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" DEPENDENCIES="doctrine/instantiator:^1.1"
-
- # 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"
+ fast_finish: true
+
+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.2
+ env: DEPENDENCIES="dunglas/symfony-lock:^2"
+ - php: 7.2
+ 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
+ env: STABILITY="dev"
- # 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:
- # Latest dev is allowed to fail.
- - 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
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ff6b43c..4e5e0a0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
# Change Log
+## 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`)
+- 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.
+- AddPathPlugin: Do not add the prefix if the URL already has the same prefix.
+
+### Removed
+- Deprecated option `debug_plugins` has been removed from `PluginClient`
+
## 1.9.0 - 2019-01-03
### Added
@@ -10,7 +25,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/composer.json b/composer.json
index c502f77..821fe16 100644
--- a/composer.json
+++ b/composer.json
@@ -11,17 +11,22 @@
}
],
"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": {
+ "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"
@@ -31,13 +36,18 @@
"Http\\Client\\Common\\": "src/"
}
},
+ "autoload-dev": {
+ "psr-4": {
+ "spec\\Http\\Client\\Common\\": "spec/"
+ }
+ },
"scripts": {
"test": "vendor/bin/phpspec run",
"test-ci": "vendor/bin/phpspec run -c phpspec.ci.yml"
},
"extra": {
"branch-alias": {
- "dev-master": "1.9.x-dev"
+ "dev-master": "2.x-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/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/spec/BatchClientSpec.php b/spec/BatchClientSpec.php
index 962f00a..86c6c8b 100644
--- a/spec/BatchClientSpec.php
+++ b/spec/BatchClientSpec.php
@@ -6,27 +6,31 @@
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
{
- function let(HttpClient $client)
+ public function let(HttpClient $client)
{
- $this->beAnInstanceOf('Http\Client\Common\BatchClient', [$client]);
+ $this->beAnInstanceOf(BatchClient::class, [$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);
- $this->sendRequests([$request1, $request2])->shouldReturnAnInstanceOf('Http\Client\Common\BatchResult');
+ $this->sendRequests([$request1, $request2])->shouldReturnAnInstanceOf(BatchResult::class);
}
- 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');
+ $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 c4618ac..90a80a5 100644
--- a/spec/BatchResultSpec.php
+++ b/spec/BatchResultSpec.php
@@ -6,24 +6,25 @@
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use PhpSpec\ObjectBehavior;
+use Http\Client\Common\BatchResult;
class BatchResultSpec extends ObjectBehavior
{
- function it_is_initializable()
+ public function it_is_initializable()
{
- $this->beAnInstanceOf('Http\Client\Common\BatchResult');
+ $this->beAnInstanceOf(BatchResult::class);
}
- function it_is_immutable(RequestInterface $request, ResponseInterface $response)
+ public function it_is_immutable(RequestInterface $request, ResponseInterface $response)
{
$new = $this->addResponse($request, $response);
$this->getResponses()->shouldReturn([]);
- $new->shouldHaveType('Http\Client\Common\BatchResult');
+ $new->shouldHaveType(BatchResult::class);
$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,17 +34,17 @@ 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);
- $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);
}
- 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..226008b 100644
--- a/spec/EmulatedHttpAsyncClientSpec.php
+++ b/spec/EmulatedHttpAsyncClientSpec.php
@@ -6,47 +6,52 @@
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
{
- 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');
+ $this->shouldHaveType(EmulatedHttpAsyncClient::class);
}
- function it_is_an_http_client()
+ public function it_is_an_http_client()
{
- $this->shouldImplement('Http\Client\HttpClient');
+ $this->shouldImplement(HttpClient::class);
}
- function it_is_an_async_http_client()
+ public function it_is_an_async_http_client()
{
- $this->shouldImplement('Http\Client\HttpAsyncClient');
+ $this->shouldImplement(HttpAsyncClient::class);
}
- function it_emulates_a_successful_request(
+ public function it_emulates_a_successful_request(
HttpClient $httpClient,
RequestInterface $request,
ResponseInterface $response
) {
$httpClient->sendRequest($request)->willReturn($response);
- $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise');
+ $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf(HttpFulfilledPromise::class);
}
- 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');
+ $httpClient->sendRequest($request)->willThrow(TransferException::class);
- $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise');
+ $this->sendAsyncRequest($request)->shouldReturnAnInstanceOf(HttpRejectedPromise::class);
}
- 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..adf206f 100644
--- a/spec/EmulatedHttpClientSpec.php
+++ b/spec/EmulatedHttpClientSpec.php
@@ -3,36 +3,38 @@
namespace spec\Http\Client\Common;
use Http\Client\Exception\TransferException;
-use Http\Client\HttpClient;
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
{
- 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');
+ $this->shouldHaveType(EmulatedHttpClient::class);
}
- function it_is_an_http_client()
+ public function it_is_an_http_client()
{
- $this->shouldImplement('Http\Client\HttpClient');
+ $this->shouldImplement(HttpClient::class);
}
- function it_is_an_async_http_client()
+ public function it_is_an_async_http_client()
{
- $this->shouldImplement('Http\Client\HttpAsyncClient');
+ $this->shouldImplement(HttpAsyncClient::class);
}
- function it_emulates_a_successful_request(
+ public function it_emulates_a_successful_request(
HttpAsyncClient $httpAsyncClient,
RequestInterface $request,
Promise $promise,
@@ -47,7 +49,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);
@@ -55,10 +57,10 @@ function it_emulates_a_failed_request(HttpAsyncClient $httpAsyncClient, RequestI
$httpAsyncClient->sendAsyncRequest($request)->willReturn($promise);
- $this->shouldThrow('Http\Client\Exception')->duringSendRequest($request);
+ $this->shouldThrow(Exception::class)->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..0205843 100644
--- a/spec/Exception/BatchExceptionSpec.php
+++ b/spec/Exception/BatchExceptionSpec.php
@@ -5,32 +5,33 @@
use Http\Client\Common\BatchResult;
use Http\Client\Exception;
use PhpSpec\ObjectBehavior;
+use Http\Client\Common\Exception\BatchException;
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');
+ $this->shouldHaveType(BatchException::class);
}
- function it_is_a_runtime_exception()
+ public function it_is_a_runtime_exception()
{
- $this->shouldHaveType('RuntimeException');
+ $this->shouldHaveType(\RuntimeException::class);
}
- function it_is_an_exception()
+ public function it_is_an_exception()
{
- $this->shouldImplement('Http\Client\Exception');
+ $this->shouldImplement(Exception::class);
}
- function it_has_a_batch_result()
+ 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 70e6e4d..b63aa3d 100644
--- a/spec/FlexibleHttpClientSpec.php
+++ b/spec/FlexibleHttpClientSpec.php
@@ -8,37 +8,38 @@
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use PhpSpec\ObjectBehavior;
+use Http\Client\Common\FlexibleHttpClient;
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');
+ $this->shouldHaveType(FlexibleHttpClient::class);
}
- function it_is_an_http_client()
+ public function it_is_an_http_client()
{
- $this->shouldImplement('Http\Client\HttpClient');
+ $this->shouldImplement(HttpClient::class);
}
- function it_is_an_async_http_client()
+ public function it_is_an_async_http_client()
{
- $this->shouldImplement('Http\Client\HttpAsyncClient');
+ $this->shouldImplement(HttpAsyncClient::class);
}
- function it_throw_exception_if_invalid_client()
+ public function it_throw_exception_if_invalid_client()
{
$this->beConstructedWith(null);
- $this->shouldThrow('\LogicException')->duringInstantiation();
+ $this->shouldThrow(\LogicException::class)->duringInstantiation();
}
- function it_emulates_an_async_client(
+ public function it_emulates_an_async_client(
HttpClient $httpClient,
RequestInterface $syncRequest,
ResponseInterface $syncResponse,
@@ -53,11 +54,11 @@ 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);
}
- function it_emulates_a_client(
+ public function it_emulates_a_client(
HttpAsyncClient $httpAsyncClient,
RequestInterface $asyncRequest,
Promise $promise,
@@ -75,10 +76,10 @@ 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');
+ $client->implement(HttpClient::class);
+ $client->implement(HttpAsyncClient::class);
$client->sendRequest($syncRequest)->shouldBeCalled();
$client->sendRequest($asyncRequest)->shouldNotBeCalled();
diff --git a/spec/HttpClientPoolItemSpec.php b/spec/HttpClientPool/HttpClientPoolItemSpec.php
similarity index 89%
rename from spec/HttpClientPoolItemSpec.php
rename to spec/HttpClientPool/HttpClientPoolItemSpec.php
index 059ec8d..22c0b7d 100644
--- a/spec/HttpClientPoolItemSpec.php
+++ b/spec/HttpClientPool/HttpClientPoolItemSpec.php
@@ -1,6 +1,6 @@
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)
@@ -156,7 +157,7 @@ public function getState()
public function wait($unwrap = true)
{
- if ($this->state === Promise::FULFILLED) {
+ if (Promise::FULFILLED === $this->state) {
if (!$unwrap) {
return;
}
@@ -164,7 +165,7 @@ public function wait($unwrap = true)
return $this->response;
}
- if ($this->state === Promise::REJECTED) {
+ if (Promise::REJECTED === $this->state) {
if (!$unwrap) {
return;
}
@@ -175,7 +176,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 +184,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 +195,7 @@ public function wait($unwrap = true)
}
}
- if ($this->response !== null) {
+ if (null !== $this->response) {
$this->state = Promise::FULFILLED;
if ($unwrap) {
@@ -202,7 +203,7 @@ public function wait($unwrap = true)
}
}
- if ($this->exception !== null) {
+ if (null !== $this->exception) {
$this->state = Promise::REJECTED;
if ($unwrap) {
diff --git a/spec/HttpClientPool/LeastUsedClientPoolSpec.php b/spec/HttpClientPool/LeastUsedClientPoolSpec.php
index a976c31..524af9b 100644
--- a/spec/HttpClientPool/LeastUsedClientPoolSpec.php
+++ b/spec/HttpClientPool/LeastUsedClientPoolSpec.php
@@ -2,37 +2,39 @@
namespace spec\Http\Client\Common\HttpClientPool;
-use Http\Client\Common\HttpClientPoolItem;
+use Http\Client\Common\HttpClientPool\HttpClientPoolItem;
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;
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)
@@ -55,27 +57,23 @@ 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)
{
- 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/spec/HttpClientPool/RandomClientPoolSpec.php b/spec/HttpClientPool/RandomClientPoolSpec.php
index 4054d82..317bcd8 100644
--- a/spec/HttpClientPool/RandomClientPoolSpec.php
+++ b/spec/HttpClientPool/RandomClientPoolSpec.php
@@ -2,7 +2,7 @@
namespace spec\Http\Client\Common\HttpClientPool;
-use Http\Client\Common\HttpClientPoolItem;
+use Http\Client\Common\HttpClientPool\HttpClientPoolItem;
use Http\Client\HttpAsyncClient;
use Http\Client\HttpClient;
use Http\Promise\Promise;
@@ -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..1b4a243 100644
--- a/spec/HttpClientPool/RoundRobinClientPoolSpec.php
+++ b/spec/HttpClientPool/RoundRobinClientPoolSpec.php
@@ -2,7 +2,7 @@
namespace spec\Http\Client\Common\HttpClientPool;
-use Http\Client\Common\HttpClientPoolItem;
+use Http\Client\Common\HttpClientPool\HttpClientPoolItem;
use Http\Client\HttpAsyncClient;
use Http\Client\HttpClient;
use Http\Promise\Promise;
@@ -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/HttpClientRouterSpec.php b/spec/HttpClientRouterSpec.php
index 1119722..a409203 100644
--- a/spec/HttpClientRouterSpec.php
+++ b/spec/HttpClientRouterSpec.php
@@ -2,6 +2,7 @@
namespace spec\Http\Client\Common;
+use Http\Client\Common\HttpClientRouter;
use Http\Message\RequestMatcher;
use Http\Client\HttpAsyncClient;
use Http\Client\HttpClient;
@@ -9,25 +10,32 @@
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use PhpSpec\ObjectBehavior;
+use Http\Client\Common\HttpClientRouterInterface;
+use Http\Client\Exception\RequestException;
class HttpClientRouterSpec extends ObjectBehavior
{
- function it_is_initializable()
+ public function it_is_initializable()
{
- $this->shouldHaveType('Http\Client\Common\HttpClientRouter');
+ $this->shouldHaveType(HttpClientRouter::class);
}
- function it_is_an_http_client()
+ public function it_is_an_http_client_router()
{
- $this->shouldImplement('Http\Client\HttpClient');
+ $this->shouldImplement(HttpClientRouterInterface::class);
}
- function it_is_an_async_http_client()
+ public function it_is_an_http_client()
{
- $this->shouldImplement('Http\Client\HttpAsyncClient');
+ $this->shouldImplement(HttpClient::class);
}
- function it_send_request(RequestMatcher $matcher, HttpClient $client, RequestInterface $request, ResponseInterface $response)
+ public function it_is_an_async_http_client()
+ {
+ $this->shouldImplement(HttpAsyncClient::class);
+ }
+
+ public function it_send_request(RequestMatcher $matcher, HttpClient $client, RequestInterface $request, ResponseInterface $response)
{
$this->addClient($client, $matcher);
$matcher->matches($request)->willReturn(true);
@@ -36,7 +44,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,19 +53,19 @@ 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);
- $this->shouldThrow('Http\Client\Exception\RequestException')->duringSendRequest($request);
+ $this->shouldThrow(RequestException::class)->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);
- $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 07c0b47..68e124d 100644
--- a/spec/HttpMethodsClientSpec.php
+++ b/spec/HttpMethodsClientSpec.php
@@ -2,115 +2,88 @@
namespace spec\Http\Client\Common;
-use Http\Client\BatchResult;
-use Http\Client\HttpClient;
use Http\Client\Common\HttpMethodsClient;
-use Http\Message\MessageFactory;
+use Http\Client\HttpClient;
+use Http\Message\RequestFactory;
+use PhpSpec\ObjectBehavior;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
-use PhpSpec\ObjectBehavior;
class HttpMethodsClientSpec extends ObjectBehavior
{
- 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(
- 'spec\Http\Client\Common\HttpMethodsClientStub', [
+ HttpMethodsClient::class, [
$client,
- $messageFactory
+ $requestFactory,
]
);
}
- 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'])->shouldReturn(true);
+ $this->assert($client, $requestFactory, $request, $response, 'get');
}
- 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'])->shouldReturn(true);
+ $this->assert($client, $requestFactory, $request, $response, 'head');
}
- 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'])->shouldReturn(true);
+ $this->assert($client, $requestFactory, $request, $response, 'trace');
}
- 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'])->shouldReturn(true);
+ $this->assert($client, $requestFactory, $request, $response, 'post', self::$requestData['body']);
}
- 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'])->shouldReturn(true);
+ $this->assert($client, $requestFactory, $request, $response, 'put', self::$requestData['body']);
}
- 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'])->shouldReturn(true);
+ $this->assert($client, $requestFactory, $request, $response, 'patch', self::$requestData['body']);
}
- 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'])->shouldReturn(true);
+ $this->assert($client, $requestFactory, $request, $response, 'delete', self::$requestData['body']);
}
- 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'])->shouldReturn(true);
+ $this->assert($client, $requestFactory, $request, $response, 'options', self::$requestData['body']);
}
- 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)
+ private function mockFactory(RequestFactory $requestFactory, RequestInterface $request, string $method, string $body = null)
{
- if (in_array($method, ['GET', 'HEAD', 'TRACE'])) {
- return $uri === self::$requestData['uri'] &&
- $headers === self::$requestData['headers'] &&
- is_null($body);
- }
-
- return in_array($method, ['POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']) &&
- $uri === self::$requestData['uri'] &&
- $headers === self::$requestData['headers'] &&
- $body === self::$requestData['body'];
+ $requestFactory->createRequest($method, self::$requestData['uri'], self::$requestData['headers'], $body)->willReturn($request);
}
}
diff --git a/spec/Plugin/AddHostPluginSpec.php b/spec/Plugin/AddHostPluginSpec.php
index caf4f21..2691f10 100644
--- a/spec/Plugin/AddHostPluginSpec.php
+++ b/spec/Plugin/AddHostPluginSpec.php
@@ -2,34 +2,34 @@
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;
+use Http\Client\Common\Plugin\AddHostPlugin;
+use Http\Client\Common\Plugin;
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');
+ $this->shouldHaveType(AddHostPlugin::class);
}
- 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');
+ $this->shouldImplement(Plugin::class);
}
- function it_adds_domain(
+ public function it_adds_domain(
RequestInterface $request,
UriInterface $host,
UriInterface $uri
@@ -47,10 +47,10 @@ function it_adds_domain(
$uri->getHost()->shouldBeCalled()->willReturn('');
$this->beConstructedWith($host);
- $this->handleRequest($request, function () {}, function () {});
+ $this->handleRequest($request, PluginStub::next(), function () {});
}
- function it_replaces_domain(
+ public function it_replaces_domain(
RequestInterface $request,
UriInterface $host,
UriInterface $uri
@@ -67,10 +67,10 @@ 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 () {});
}
- function it_does_nothing_when_domain_exists(
+ public function it_does_nothing_when_domain_exists(
RequestInterface $request,
UriInterface $host,
UriInterface $uri
@@ -79,6 +79,6 @@ 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 6838ed8..1c6f09d 100644
--- a/spec/Plugin/AddPathPluginSpec.php
+++ b/spec/Plugin/AddPathPluginSpec.php
@@ -2,34 +2,34 @@
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;
+use Http\Client\Common\Plugin\AddPathPlugin;
+use Http\Client\Common\Plugin;
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');
+ $this->shouldHaveType(AddPathPlugin::class);
}
- 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');
+ $this->shouldImplement(Plugin::class);
}
- function it_adds_path(
+ public function it_adds_path(
RequestInterface $request,
UriInterface $host,
UriInterface $uri
@@ -37,16 +37,16 @@ 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);
- $this->handleRequest($request, function () {}, function () {});
+ $this->handleRequest($request, PluginStub::next(), function () {});
}
- function it_removes_ending_slashes(
+ public function it_removes_ending_slashes(
RequestInterface $request,
UriInterface $host,
UriInterface $host2,
@@ -63,14 +63,14 @@ function it_removes_ending_slashes(
$uri->getPath()->shouldBeCalled()->willReturn('/users');
$this->beConstructedWith($host);
- $this->handleRequest($request, function () {}, function () {});
+ $this->handleRequest($request, PluginStub::next(), function () {});
}
- function it_throws_exception_on_empty_path(UriInterface $host)
+ 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 02d1187..c86cb3a 100644
--- a/spec/Plugin/AuthenticationPluginSpec.php
+++ b/spec/Plugin/AuthenticationPluginSpec.php
@@ -7,29 +7,31 @@
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
{
- 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');
+ $this->shouldHaveType(AuthenticationPlugin::class);
}
- function it_is_a_plugin()
+ public function it_is_a_plugin()
{
- $this->shouldImplement('Http\Client\Common\Plugin');
+ $this->shouldImplement(Plugin::class);
}
- 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..92f5074 100644
--- a/spec/Plugin/BaseUriPluginSpec.php
+++ b/spec/Plugin/BaseUriPluginSpec.php
@@ -2,36 +2,36 @@
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;
+use Http\Client\Common\Plugin\BaseUriPlugin;
+use Http\Client\Common\Plugin;
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');
- $this->shouldHaveType('Http\Client\Common\Plugin\BaseUriPlugin');
+ $this->shouldHaveType(BaseUriPlugin::class);
}
- 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');
- $this->shouldImplement('Http\Client\Common\Plugin');
+ $this->shouldImplement(Plugin::class);
}
- function it_adds_domain_and_path(
+ public function it_adds_domain_and_path(
RequestInterface $request,
UriInterface $host,
UriInterface $uri
@@ -52,10 +52,10 @@ 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 () {});
}
- function it_adds_domain(
+ public function it_adds_domain(
RequestInterface $request,
UriInterface $host,
UriInterface $uri
@@ -74,10 +74,10 @@ function it_adds_domain(
$uri->getHost()->shouldBeCalled()->willReturn('');
$this->beConstructedWith($host);
- $this->handleRequest($request, function () {}, function () {});
+ $this->handleRequest($request, PluginStub::next(), function () {});
}
- function it_replaces_domain_and_adds_path(
+ public function it_replaces_domain_and_adds_path(
RequestInterface $request,
UriInterface $host,
UriInterface $uri
@@ -97,6 +97,6 @@ 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 4ec2ba7..a945924 100644
--- a/spec/Plugin/ContentLengthPluginSpec.php
+++ b/spec/Plugin/ContentLengthPluginSpec.php
@@ -7,32 +7,34 @@
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
{
- function it_is_initializable()
+ public function it_is_initializable()
{
- $this->shouldHaveType('Http\Client\Common\Plugin\ContentLengthPlugin');
+ $this->shouldHaveType(ContentLengthPlugin::class);
}
- function it_is_a_plugin()
+ public function it_is_a_plugin()
{
- $this->shouldImplement('Http\Client\Common\Plugin');
+ $this->shouldImplement(Plugin::class);
}
- 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);
$stream->getSize()->shouldBeCalled()->willReturn(100);
$request->withHeader('Content-Length', '100')->shouldBeCalled()->willReturn($request);
- $this->handleRequest($request, function () {}, function () {});
+ $this->handleRequest($request, PluginStub::next(), 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');
}
@@ -43,6 +45,6 @@ function it_streams_chunked_if_no_size(RequestInterface $request, StreamInterfac
$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 3df7d87..a27d32a 100644
--- a/spec/Plugin/ContentTypePluginSpec.php
+++ b/spec/Plugin/ContentTypePluginSpec.php
@@ -2,108 +2,106 @@
namespace spec\Http\Client\Common\Plugin;
-use PhpSpec\Exception\Example\SkippingException;
-use Psr\Http\Message\RequestInterface;
-use Psr\Http\Message\StreamInterface;
+use Http\Client\Common\Plugin;
+use Http\Client\Common\Plugin\ContentTypePlugin;
use PhpSpec\ObjectBehavior;
-use Prophecy\Argument;
+use Psr\Http\Message\RequestInterface;
class ContentTypePluginSpec extends ObjectBehavior
{
- function it_is_initializable()
+ public function it_is_initializable()
{
- $this->shouldHaveType('Http\Client\Common\Plugin\ContentTypePlugin');
+ $this->shouldHaveType(ContentTypePlugin::class);
}
- function it_is_a_plugin()
+ public function it_is_a_plugin()
{
- $this->shouldImplement('Http\Client\Common\Plugin');
+ $this->shouldImplement(Plugin::class);
}
- 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'])));
$request->withHeader('Content-Type', 'application/json')->shouldBeCalled()->willReturn($request);
- $this->handleRequest($request, function () {}, function () {});
+ $this->handleRequest($request, PluginStub::next(), 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'));
$request->withHeader('Content-Type', 'application/xml')->shouldBeCalled()->willReturn($request);
- $this->handleRequest($request, function () {}, function () {});
+ $this->handleRequest($request, PluginStub::next(), 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'));
$request->withHeader('Content-Type', null)->shouldNotBeCalled();
- $this->handleRequest($request, function () {}, function () {});
+ $this->handleRequest($request, PluginStub::next(), 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'));
$request->withHeader('Content-Type', null)->shouldNotBeCalled();
- $this->handleRequest($request, function () {}, function () {});
+ $this->handleRequest($request, PluginStub::next(), 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());
$request->withHeader('Content-Type', null)->shouldNotBeCalled();
- $this->handleRequest($request, function () {}, function () {});
+ $this->handleRequest($request, PluginStub::next(), 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);
$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 () {});
}
- 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);
$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 () {});
}
- 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);
$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 2bb47e7..7bb188c 100644
--- a/spec/Plugin/CookiePluginSpec.php
+++ b/spec/Plugin/CookiePluginSpec.php
@@ -10,30 +10,33 @@
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
{
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');
+ $this->shouldHaveType(CookiePlugin::class);
}
- function it_is_a_plugin()
+ public function it_is_a_plugin()
{
- $this->shouldImplement('Http\Client\Common\Plugin');
+ $this->shouldImplement(Plugin::class);
}
- 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);
@@ -44,14 +47,10 @@ function it_loads_cookie(RequestInterface $request, UriInterface $uri, Promise $
$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 () {});
}
- 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');
@@ -65,28 +64,20 @@ function it_combines_multiple_cookies_into_one_header(RequestInterface $request,
$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 () {});
}
- 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);
$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 () {});
}
- 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);
@@ -96,14 +87,10 @@ function it_does_not_load_cookie_if_domain_does_not_match(RequestInterface $requ
$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 () {});
}
- 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',
@@ -118,15 +105,11 @@ function it_does_not_load_cookie_on_hackish_domains(RequestInterface $request, U
$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 () {});
}
}
- 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);
@@ -137,14 +120,10 @@ function it_loads_cookie_on_subdomains(RequestInterface $request, UriInterface $
$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 () {});
}
- 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);
@@ -155,14 +134,10 @@ function it_does_not_load_cookie_if_path_does_not_match(RequestInterface $reques
$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 () {});
}
- 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);
@@ -174,14 +149,10 @@ function it_does_not_load_cookie_when_cookie_is_secure(RequestInterface $request
$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 () {});
}
- 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);
@@ -193,14 +164,10 @@ function it_loads_cookie_when_cookie_is_secure(RequestInterface $request, UriInt
$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 () {});
}
- 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 +175,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);
@@ -216,11 +183,11 @@ function it_saves_cookie(RequestInterface $request, ResponseInterface $response,
$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);
}
- 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 +198,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);
@@ -239,7 +206,7 @@ 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 7543027..1316a90 100644
--- a/spec/Plugin/DecoderPluginSpec.php
+++ b/spec/Plugin/DecoderPluginSpec.php
@@ -9,28 +9,32 @@
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
{
- function it_is_initializable()
+ public function it_is_initializable()
{
- $this->shouldHaveType('Http\Client\Common\Plugin\DecoderPlugin');
+ $this->shouldHaveType(DecoderPlugin::class);
}
- function it_is_a_plugin()
+ public function it_is_a_plugin()
{
- $this->shouldImplement('Http\Client\Common\Plugin');
+ $this->shouldImplement(Plugin::class);
}
- 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 +52,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());
};
@@ -60,7 +64,7 @@ function it_decodes_gzip(RequestInterface $request, ResponseInterface $response,
$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);
@@ -70,11 +74,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());
};
@@ -82,7 +86,7 @@ function it_decodes_deflate(RequestInterface $request, ResponseInterface $respon
$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);
@@ -92,13 +96,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..67e5c7e 100644
--- a/spec/Plugin/ErrorPluginSpec.php
+++ b/spec/Plugin/ErrorPluginSpec.php
@@ -7,77 +7,82 @@
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
{
- function it_is_initializable()
+ public function it_is_initializable()
{
- $this->beAnInstanceOf('Http\Client\Common\Plugin\ErrorPlugin');
+ $this->beAnInstanceOf(ErrorPlugin::class);
}
- function it_is_a_plugin()
+ public function it_is_a_plugin()
{
- $this->shouldImplement('Http\Client\Common\Plugin');
+ $this->shouldImplement(Plugin::class);
}
- 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());
}
};
$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();
}
- 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());
}
};
- $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise');
+ $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf(HttpFulfilledPromise::class);
}
- 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());
}
};
$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();
}
- 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());
}
};
- $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 24b8565..9325069 100644
--- a/spec/Plugin/HeaderAppendPluginSpec.php
+++ b/spec/Plugin/HeaderAppendPluginSpec.php
@@ -2,36 +2,35 @@
namespace spec\Http\Client\Common\Plugin;
-use PhpSpec\Exception\Example\SkippingException;
-use Psr\Http\Message\RequestInterface;
-use Psr\Http\Message\StreamInterface;
+use Http\Client\Common\Plugin;
+use Http\Client\Common\Plugin\HeaderAppendPlugin;
use PhpSpec\ObjectBehavior;
-use Prophecy\Argument;
+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)
{
$this->beConstructedWith([
- 'foo'=>'bar',
- 'baz'=>'qux'
+ 'foo' => 'bar',
+ 'baz' => 'qux',
]);
$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 341f1a5..5a50a9c 100644
--- a/spec/Plugin/HeaderDefaultsPluginSpec.php
+++ b/spec/Plugin/HeaderDefaultsPluginSpec.php
@@ -2,37 +2,36 @@
namespace spec\Http\Client\Common\Plugin;
-use PhpSpec\Exception\Example\SkippingException;
-use Psr\Http\Message\RequestInterface;
-use Psr\Http\Message\StreamInterface;
+use Http\Client\Common\Plugin;
+use Http\Client\Common\Plugin\HeaderDefaultsPlugin;
use PhpSpec\ObjectBehavior;
-use Prophecy\Argument;
+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)
{
$this->beConstructedWith([
'foo' => 'bar',
- 'baz' => 'qux'
+ 'baz' => 'qux',
]);
$request->hasHeader('foo')->shouldBeCalled()->willReturn(false);
$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 9ea2752..3f60359 100644
--- a/spec/Plugin/HeaderRemovePluginSpec.php
+++ b/spec/Plugin/HeaderRemovePluginSpec.php
@@ -2,31 +2,30 @@
namespace spec\Http\Client\Common\Plugin;
-use PhpSpec\Exception\Example\SkippingException;
-use Psr\Http\Message\RequestInterface;
-use Psr\Http\Message\StreamInterface;
+use Http\Client\Common\Plugin;
+use Http\Client\Common\Plugin\HeaderRemovePlugin;
use PhpSpec\ObjectBehavior;
-use Prophecy\Argument;
+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)
{
$this->beConstructedWith([
'foo',
- 'baz'
+ 'baz',
]);
$request->hasHeader('foo')->shouldBeCalled()->willReturn(false);
@@ -34,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 f4a340c..b152567 100644
--- a/spec/Plugin/HeaderSetPluginSpec.php
+++ b/spec/Plugin/HeaderSetPluginSpec.php
@@ -2,36 +2,35 @@
namespace spec\Http\Client\Common\Plugin;
-use PhpSpec\Exception\Example\SkippingException;
-use Psr\Http\Message\RequestInterface;
-use Psr\Http\Message\StreamInterface;
+use Http\Client\Common\Plugin;
+use Http\Client\Common\Plugin\HeaderSetPlugin;
use PhpSpec\ObjectBehavior;
-use Prophecy\Argument;
+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)
{
$this->beConstructedWith([
- 'foo'=>'bar',
- 'baz'=>'qux'
+ 'foo' => 'bar',
+ 'baz' => 'qux',
]);
$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 24e7f51..495e5d5 100644
--- a/spec/Plugin/HistoryPluginSpec.php
+++ b/spec/Plugin/HistoryPluginSpec.php
@@ -10,27 +10,28 @@
use Psr\Http\Message\ResponseInterface;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
+use Http\Client\Common\Plugin;
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');
+ $this->shouldImplement(Plugin::class);
}
- 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 +42,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/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)
@@ -35,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)
@@ -52,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 97197e1..de9b30a 100644
--- a/spec/Plugin/RedirectPluginSpec.php
+++ b/spec/Plugin/RedirectPluginSpec.php
@@ -2,28 +2,33 @@
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
{
- function it_is_initializable()
+ public function it_is_initializable()
{
- $this->shouldHaveType('Http\Client\Common\Plugin\RedirectPlugin');
+ $this->shouldHaveType(RedirectPlugin::class);
}
- function it_is_a_plugin()
+ public function it_is_a_plugin()
{
- $this->shouldImplement('Http\Client\Common\Plugin');
+ $this->shouldImplement(Plugin::class);
}
- function it_redirects_on_302(
+ public function it_redirects_on_302(
UriInterface $uri,
UriInterface $uriRedirect,
RequestInterface $request,
@@ -48,14 +53,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();
}
@@ -65,55 +69,23 @@ 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);
}
- 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');
-
- $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, function () {});
- }
-
- 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('spec\Http\Client\Common\Plugin\RedirectPluginStub');
- $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);
@@ -121,26 +93,58 @@ 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);
}
- function it_replace_full_url(
+ 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(
UriInterface $uri,
UriInterface $uriRedirect,
RequestInterface $request,
@@ -171,13 +175,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 +193,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());
}
@@ -203,13 +207,13 @@ function it_throws_http_exception_on_no_location(RequestInterface $request, UriI
$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();
}
- 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());
}
@@ -223,13 +227,13 @@ function it_throws_http_exception_on_invalid_location(RequestInterface $request,
$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();
}
- 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());
}
@@ -239,13 +243,13 @@ function it_throw_multi_redirect_exception_on_300(RequestInterface $request, Res
$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();
}
- 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());
}
@@ -255,11 +259,11 @@ function it_throw_multi_redirect_exception_on_300_if_no_location(RequestInterfac
$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();
}
- function it_switch_method_for_302(
+ public function it_switch_method_for_302(
UriInterface $uri,
UriInterface $uriRedirect,
RequestInterface $request,
@@ -288,13 +292,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 +310,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 +342,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,41 +360,106 @@ 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)
- {
- $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('spec\Http\Client\Common\Plugin\RedirectPluginStubCircular');
- $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('Http\Client\Promise\HttpRejectedPromise');
- $promise->shouldThrow('Http\Client\Common\Exception\CircularRedirectionException')->duringWait();
+ $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class);
+ $promise->shouldThrow(CircularRedirectionException::class)->duringWait();
}
- function it_redirects_http_to_https(
+ public function it_redirects_http_to_https(
UriInterface $uri,
UriInterface $uriRedirect,
RequestInterface $request,
@@ -417,13 +486,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();
}
@@ -433,37 +502,7 @@ 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);
}
}
-
-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/spec/Plugin/RequestMatcherPluginSpec.php b/spec/Plugin/RequestMatcherPluginSpec.php
index 4fe9aea..de7cae6 100644
--- a/spec/Plugin/RequestMatcherPluginSpec.php
+++ b/spec/Plugin/RequestMatcherPluginSpec.php
@@ -8,25 +8,26 @@
use Psr\Http\Message\RequestInterface;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
+use Http\Client\Common\Plugin\RequestMatcherPlugin;
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');
+ $this->shouldHaveType(RequestMatcherPlugin::class);
}
- function it_is_a_plugin()
+ public function it_is_a_plugin()
{
- $this->shouldImplement('Http\Client\Common\Plugin');
+ $this->shouldImplement(Plugin::class);
}
- 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
@@ -34,10 +35,10 @@ 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 () {});
}
- function it_does_not_match_a_request(
+ public function it_does_not_match_a_request(
RequestInterface $request,
RequestMatcher $requestMatcher,
Plugin $plugin,
@@ -46,7 +47,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 4a985f3..e01ba54 100644
--- a/spec/Plugin/RetryPluginSpec.php
+++ b/spec/Plugin/RetryPluginSpec.php
@@ -9,88 +9,112 @@
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
{
- function it_is_initializable()
+ public function it_is_initializable()
{
- $this->shouldHaveType('Http\Client\Common\Plugin\RetryPlugin');
+ $this->shouldHaveType(RetryPlugin::class);
}
- function it_is_a_plugin()
+ public function it_is_a_plugin()
{
- $this->shouldImplement('Http\Client\Common\Plugin');
+ $this->shouldImplement(Plugin::class);
}
- 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());
}
};
- $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise');
+ $this->handleRequest($request, $next, function () {})->shouldReturnAnInstanceOf(HttpFulfilledPromise::class);
}
- 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);
}
}
};
$promise = $this->handleRequest($request, $next, function () {});
- $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpRejectedPromise');
+ $promise->shouldReturnAnInstanceOf(HttpRejectedPromise::class);
$promise->shouldThrow($exception2)->duringWait();
}
- function it_returns_response_on_second_try(RequestInterface $request, ResponseInterface $response)
+ 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());
$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());
}
}
};
$promise = $this->handleRequest($request, $next, function () {});
- $promise->shouldReturnAnInstanceOf('Http\Client\Promise\HttpFulfilledPromise');
+ $promise->shouldReturnAnInstanceOf(HttpFulfilledPromise::class);
$promise->wait()->shouldReturn($response);
}
- function it_respects_custom_exception_decider(RequestInterface $request, ResponseInterface $response)
+ public function it_respects_custom_exception_decider(RequestInterface $request, ResponseInterface $response)
{
$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');
}
@@ -104,29 +128,29 @@ function it_respects_custom_exception_decider(RequestInterface $request, Respons
$promise->shouldThrow($exception)->duringWait();
}
- 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());
}
}
};
- $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);
}
- 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..d7a3acb 100644
--- a/spec/PluginClientFactorySpec.php
+++ b/spec/PluginClientFactorySpec.php
@@ -4,22 +4,24 @@
use Http\Client\HttpClient;
use PhpSpec\ObjectBehavior;
+use Http\Client\Common\PluginClientFactory;
+use Http\Client\Common\PluginClient;
class PluginClientFactorySpec extends ObjectBehavior
{
- function it_is_initializable()
+ public function it_is_initializable()
{
- $this->shouldHaveType('Http\Client\Common\PluginClientFactory');
+ $this->shouldHaveType(PluginClientFactory::class);
}
- 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');
+ $client->shouldHaveType(PluginClient::class);
}
- 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 addb2e8..c5c2932 100644
--- a/spec/PluginClientSpec.php
+++ b/spec/PluginClientSpec.php
@@ -4,44 +4,45 @@
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;
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
{
- 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');
+ $this->shouldHaveType(PluginClient::class);
}
- function it_is_an_http_client()
+ public function it_is_an_http_client()
{
- $this->shouldImplement('Http\Client\HttpClient');
+ $this->shouldImplement(HttpClient::class);
}
- function it_is_an_http_async_client()
+ public function it_is_an_http_async_client()
{
- $this->shouldImplement('Http\Client\HttpAsyncClient');
+ $this->shouldImplement(HttpAsyncClient::class);
}
- 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 +50,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,10 +59,10 @@ 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');
+ $client->implement(HttpClient::class);
+ $client->implement(HttpAsyncClient::class);
$client->sendRequest($request)->willReturn($response);
@@ -70,7 +71,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(
@@ -85,49 +86,6 @@ function it_throws_loop_exception(HttpClient $httpClient, RequestInterface $requ
$this->beConstructedWith($httpClient, [$plugin]);
- $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);
+ $this->shouldThrow(LoopException::class)->duringSendRequest($request);
}
}
diff --git a/src/BatchClient.php b/src/BatchClient.php
index 1aa9950..bd340af 100644
--- a/src/BatchClient.php
+++ b/src/BatchClient.php
@@ -1,62 +1,33 @@
- */
-class BatchClient implements HttpClient
+final class BatchClient implements BatchClientInterface
{
/**
- * @var HttpClient|ClientInterface
+ * @var ClientInterface
*/
private $client;
- /**
- * @param HttpClient|ClientInterface $client
- */
- public function __construct($client)
+ public function __construct(ClientInterface $client)
{
- if (!($client instanceof HttpClient) && !($client instanceof ClientInterface)) {
- throw new \LogicException('Client must be an instance of Http\\Client\\HttpClient or Psr\\Http\\Client\\ClientInterface');
- }
-
$this->client = $client;
}
- /**
- * {@inheritdoc}
- */
- public function sendRequest(RequestInterface $request)
+ 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)
+ 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..56a34ae
--- /dev/null
+++ b/src/BatchClientInterface.php
@@ -0,0 +1,35 @@
+
+ */
+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/BatchResult.php b/src/BatchResult.php
index 710611d..4202c70 100644
--- a/src/BatchResult.php
+++ b/src/BatchResult.php
@@ -1,5 +1,7 @@
responses->count() > 0;
}
@@ -44,7 +44,7 @@ public function hasResponses()
*
* @return ResponseInterface[]
*/
- public function getResponses()
+ public function getResponses(): array
{
$responses = [];
@@ -57,12 +57,8 @@ public function getResponses()
/**
* Checks if there is a successful response for a request.
- *
- * @param RequestInterface $request
- *
- * @return bool
*/
- public function isSuccessful(RequestInterface $request)
+ public function isSuccessful(RequestInterface $request): bool
{
return $this->responses->contains($request);
}
@@ -70,13 +66,10 @@ 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
*/
- public function getResponseFor(RequestInterface $request)
+ public function getResponseFor(RequestInterface $request): ResponseInterface
{
try {
return $this->responses[$request];
@@ -88,12 +81,9 @@ 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)
+ public function addResponse(RequestInterface $request, ResponseInterface $response): self
{
$new = clone $this;
$new->responses->attach($request, $response);
@@ -103,10 +93,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;
}
@@ -116,7 +104,7 @@ public function hasExceptions()
*
* @return Exception[]
*/
- public function getExceptions()
+ public function getExceptions(): array
{
$exceptions = [];
@@ -129,12 +117,8 @@ 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)
+ public function isFailed(RequestInterface $request): bool
{
return $this->exceptions->contains($request);
}
@@ -142,13 +126,10 @@ 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
*/
- public function getExceptionFor(RequestInterface $request)
+ public function getExceptionFor(RequestInterface $request): Exception
{
try {
return $this->exceptions[$request];
@@ -160,12 +141,9 @@ 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)
+ 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..7c3f9f5 100644
--- a/src/Deferred.php
+++ b/src/Deferred.php
@@ -1,5 +1,7 @@
waitCallback);
@@ -69,7 +71,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/EmulatedHttpAsyncClient.php b/src/EmulatedHttpAsyncClient.php
index 39f89cc..008f888 100644
--- a/src/EmulatedHttpAsyncClient.php
+++ b/src/EmulatedHttpAsyncClient.php
@@ -1,5 +1,7 @@
*/
-class EmulatedHttpAsyncClient implements HttpClient, HttpAsyncClient
+final class EmulatedHttpAsyncClient implements HttpClient, HttpAsyncClient
{
use HttpAsyncClientEmulator;
use HttpClientDecorator;
- /**
- * @param HttpClient|ClientInterface $httpClient
- */
- public function __construct($httpClient)
+ public function __construct(ClientInterface $httpClient)
{
- if (!($httpClient instanceof HttpClient) && !($httpClient instanceof ClientInterface)) {
- throw new \LogicException('Client must be an instance of Http\\Client\\HttpClient or Psr\\Http\\Client\\ClientInterface');
- }
-
$this->httpClient = $httpClient;
}
}
diff --git a/src/EmulatedHttpClient.php b/src/EmulatedHttpClient.php
index 01046c8..5c2d8c4 100644
--- a/src/EmulatedHttpClient.php
+++ b/src/EmulatedHttpClient.php
@@ -1,25 +1,22 @@
*/
-class EmulatedHttpClient implements HttpClient, HttpAsyncClient
+final 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..5167842 100644
--- a/src/Exception/BatchException.php
+++ b/src/Exception/BatchException.php
@@ -1,5 +1,7 @@
result = $result;
diff --git a/src/Exception/CircularRedirectionException.php b/src/Exception/CircularRedirectionException.php
index 73ec521..de2063e 100644
--- a/src/Exception/CircularRedirectionException.php
+++ b/src/Exception/CircularRedirectionException.php
@@ -1,5 +1,7 @@
httpClient = $client;
$this->httpAsyncClient = $client;
- if (!($this->httpClient instanceof HttpClient) && !($client instanceof ClientInterface)) {
+ if (!($this->httpClient instanceof ClientInterface)) {
$this->httpClient = new EmulatedHttpClient($this->httpClient);
}
diff --git a/src/HttpAsyncClientDecorator.php b/src/HttpAsyncClientDecorator.php
index 6eb576c..2714b4a 100644
--- a/src/HttpAsyncClientDecorator.php
+++ b/src/HttpAsyncClientDecorator.php
@@ -1,5 +1,7 @@
httpClient->sendRequest($request);
}
diff --git a/src/HttpClientEmulator.php b/src/HttpClientEmulator.php
index dbec1ab..51e2c05 100644
--- a/src/HttpClientEmulator.php
+++ b/src/HttpClientEmulator.php
@@ -1,8 +1,11 @@
sendAsyncRequest($request);
diff --git a/src/HttpClientPool.php b/src/HttpClientPool.php
index 7ac292c..9e979eb 100644
--- a/src/HttpClientPool.php
+++ b/src/HttpClientPool.php
@@ -1,59 +1,24 @@
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();
-
- /**
- * {@inheritdoc}
- */
- public function sendAsyncRequest(RequestInterface $request)
- {
- return $this->chooseHttpClient()->sendAsyncRequest($request);
- }
-
- /**
- * {@inheritdoc}
+ * @param ClientInterface|HttpAsyncClient|HttpClientPoolItem $client
*/
- public function sendRequest(RequestInterface $request)
- {
- 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..0c417c0
--- /dev/null
+++ b/src/HttpClientPool/HttpClientPool.php
@@ -0,0 +1,63 @@
+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 67%
rename from src/HttpClientPoolItem.php
rename to src/HttpClientPool/HttpClientPoolItem.php
index 09cd6dd..47c9eb2 100644
--- a/src/HttpClientPoolItem.php
+++ b/src/HttpClientPool/HttpClientPoolItem.php
@@ -1,17 +1,29 @@
*/
@@ -28,7 +40,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;
@@ -38,8 +54,8 @@ class HttpClientPoolItem implements HttpClient, HttpAsyncClient
private $client;
/**
- * @param HttpClient|HttpAsyncClient $client
- * @param null|int $reenableAfter Number of seconds after this client is reenable
+ * @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)
{
@@ -50,7 +66,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);
@@ -96,21 +112,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;
@@ -119,31 +130,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 6299cce..789c357 100644
--- a/src/HttpClientPool/LeastUsedClientPool.php
+++ b/src/HttpClientPool/LeastUsedClientPool.php
@@ -1,10 +1,10 @@
clientPool, function (HttpClientPoolItem $clientPoolItem) {
return !$clientPoolItem->isDisabled();
diff --git a/src/HttpClientPool/RandomClientPool.php b/src/HttpClientPool/RandomClientPool.php
index 3255f86..789ba42 100644
--- a/src/HttpClientPool/RandomClientPool.php
+++ b/src/HttpClientPool/RandomClientPool.php
@@ -1,10 +1,10 @@
clientPool, function (HttpClientPoolItem $clientPoolItem) {
return !$clientPoolItem->isDisabled();
diff --git a/src/HttpClientPool/RoundRobinClientPool.php b/src/HttpClientPool/RoundRobinClientPool.php
index 8d8e40a..7c7b191 100644
--- a/src/HttpClientPool/RoundRobinClientPool.php
+++ b/src/HttpClientPool/RoundRobinClientPool.php
@@ -1,9 +1,10 @@
clientPool);
diff --git a/src/HttpClientRouter.php b/src/HttpClientRouter.php
index 9f72133..37f8c3c 100644
--- a/src/HttpClientRouter.php
+++ b/src/HttpClientRouter.php
@@ -1,19 +1,23 @@
*/
-final class HttpClientRouter implements HttpClient, HttpAsyncClient
+final class HttpClientRouter implements HttpClientRouterInterface
{
/**
* @var array
@@ -23,11 +27,9 @@ final class HttpClientRouter implements HttpClient, HttpAsyncClient
/**
* {@inheritdoc}
*/
- public function sendRequest(RequestInterface $request)
+ public function sendRequest(RequestInterface $request): ResponseInterface
{
- $client = $this->chooseHttpClient($request);
-
- return $client->sendRequest($request);
+ return $this->chooseHttpClient($request)->sendRequest($request);
}
/**
@@ -35,16 +37,13 @@ public function sendRequest(RequestInterface $request)
*/
public function sendAsyncRequest(RequestInterface $request)
{
- $client = $this->chooseHttpClient($request);
-
- return $client->sendAsyncRequest($request);
+ return $this->chooseHttpClient($request)->sendAsyncRequest($request);
}
/**
* Add a client to the router.
*
* @param HttpClient|HttpAsyncClient $client
- * @param RequestMatcher $requestMatcher
*/
public function addClient($client, RequestMatcher $requestMatcher)
{
@@ -57,11 +56,9 @@ public function addClient($client, RequestMatcher $requestMatcher)
/**
* Choose an HTTP client given a specific request.
*
- * @param RequestInterface $request
- *
- * @return HttpClient|HttpAsyncClient
+ * @return ClientInterface|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/HttpClientRouterInterface.php b/src/HttpClientRouterInterface.php
new file mode 100644
index 0000000..4526e7f
--- /dev/null
+++ b/src/HttpClientRouterInterface.php
@@ -0,0 +1,27 @@
+
+ */
+interface HttpClientRouterInterface extends HttpClient, HttpAsyncClient
+{
+ /**
+ * Add a client to the router.
+ *
+ * @param ClientInterface|HttpAsyncClient $client
+ */
+ public function addClient($client, RequestMatcher $requestMatcher);
+}
diff --git a/src/HttpMethodsClient.php b/src/HttpMethodsClient.php
index c462c10..9c53c71 100644
--- a/src/HttpMethodsClient.php
+++ b/src/HttpMethodsClient.php
@@ -1,34 +1,18 @@
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|ClientInterface
+ * @var ClientInterface
*/
private $httpClient;
@@ -38,157 +22,56 @@ class HttpMethodsClient implements HttpClient
private $requestFactory;
/**
- * @param HttpClient|ClientInterface $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, RequestFactory $requestFactory)
+ public function __construct(ClientInterface $httpClient, RequestFactory $requestFactory)
{
- if (!($httpClient instanceof HttpClient) && !($httpClient instanceof ClientInterface)) {
- throw new \LogicException('Client must be an instance of Http\\Client\\HttpClient or Psr\\Http\\Client\\ClientInterface');
- }
-
$this->httpClient = $httpClient;
$this->requestFactory = $requestFactory;
}
- /**
- * Sends a GET request.
- *
- * @param string|UriInterface $uri
- * @param array $headers
- *
- * @throws Exception
- *
- * @return ResponseInterface
- */
- public function get($uri, array $headers = [])
+ public function get($uri, array $headers = []): ResponseInterface
{
return $this->send('GET', $uri, $headers, null);
}
- /**
- * Sends an HEAD request.
- *
- * @param string|UriInterface $uri
- * @param array $headers
- *
- * @throws Exception
- *
- * @return ResponseInterface
- */
- public function head($uri, array $headers = [])
+ public function head($uri, array $headers = []): ResponseInterface
{
return $this->send('HEAD', $uri, $headers, null);
}
- /**
- * Sends a TRACE request.
- *
- * @param string|UriInterface $uri
- * @param array $headers
- *
- * @throws Exception
- *
- * @return ResponseInterface
- */
- public function trace($uri, array $headers = [])
+ public function trace($uri, array $headers = []): ResponseInterface
{
return $this->send('TRACE', $uri, $headers, null);
}
- /**
- * Sends a POST request.
- *
- * @param string|UriInterface $uri
- * @param 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);
}
- /**
- * Sends a PUT request.
- *
- * @param string|UriInterface $uri
- * @param array $headers
- * @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);
}
- /**
- * Sends a PATCH request.
- *
- * @param string|UriInterface $uri
- * @param array $headers
- * @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);
}
- /**
- * Sends a DELETE request.
- *
- * @param string|UriInterface $uri
- * @param array $headers
- * @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);
}
- /**
- * Sends an OPTIONS request.
- *
- * @param string|UriInterface $uri
- * @param array $headers
- * @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);
}
- /**
- * Sends a request with any HTTP method.
- *
- * @param string $method HTTP method to use
- * @param string|UriInterface $uri
- * @param array $headers
- * @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,
@@ -198,12 +81,7 @@ public function send($method, $uri, array $headers = [], $body = null)
));
}
- /**
- * Forward to the underlying HttpClient.
- *
- * {@inheritdoc}
- */
- public function sendRequest(RequestInterface $request)
+ 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..20fbf03
--- /dev/null
+++ b/src/HttpMethodsClientInterface.php
@@ -0,0 +1,116 @@
+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;
+}
diff --git a/src/Plugin.php b/src/Plugin.php
index 89a2a62..cbc9592 100644
--- a/src/Plugin.php
+++ b/src/Plugin.php
@@ -1,5 +1,7 @@
replace || '' === $request->getUri()->getHost()) {
$uri = $request->getUri()
@@ -64,9 +66,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 0a1bca2..9d43104 100644
--- a/src/Plugin/AddPathPlugin.php
+++ b/src/Plugin/AddPathPlugin.php
@@ -1,8 +1,11 @@
getPath()) {
@@ -42,17 +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)
+ 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)) {
+ if (substr($path, 0, strlen($prepend)) !== $prepend) {
$request = $request->withUri($request->getUri()
- ->withPath($this->uri->getPath().$request->getUri()->getPath())
- );
- $this->alteredRequests[$identifier] = $identifier;
+ ->withPath($prepend.$path)
+ );
}
return $next($request);
diff --git a/src/Plugin/AuthenticationPlugin.php b/src/Plugin/AuthenticationPlugin.php
index 194712f..ce9d4bd 100644
--- a/src/Plugin/AuthenticationPlugin.php
+++ b/src/Plugin/AuthenticationPlugin.php
@@ -1,9 +1,12 @@
authentication = $authentication;
@@ -29,7 +29,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 2c2a775..825709b 100644
--- a/src/Plugin/BaseUriPlugin.php
+++ b/src/Plugin/BaseUriPlugin.php
@@ -1,8 +1,11 @@
addHostPlugin->handleRequest($request, $next, $first);
diff --git a/src/Plugin/ContentLengthPlugin.php b/src/Plugin/ContentLengthPlugin.php
index 0f7aafa..f313c33 100644
--- a/src/Plugin/ContentLengthPlugin.php
+++ b/src/Plugin/ContentLengthPlugin.php
@@ -1,9 +1,12 @@
hasHeader('Content-Length')) {
$stream = $request->getBody();
diff --git a/src/Plugin/ContentTypePlugin.php b/src/Plugin/ContentTypePlugin.php
index 8ef1d62..f3944dd 100644
--- a/src/Plugin/ContentTypePlugin.php
+++ b/src/Plugin/ContentTypePlugin.php
@@ -1,8 +1,11 @@
hasHeader('Content-Type')) {
$stream = $request->getBody();
@@ -91,13 +94,11 @@ public function handleRequest(RequestInterface $request, callable $next, callabl
return $next($request);
}
- /**
- * @param $stream StreamInterface
- *
- * @return bool
- */
- private function isJson($stream)
+ private function isJson(StreamInterface $stream): bool
{
+ if (!function_exists('json_decode')) {
+ return false;
+ }
$stream->rewind();
json_decode($stream->getContents());
@@ -107,17 +108,18 @@ private function isJson($stream)
/**
* @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 156532a..8399210 100644
--- a/src/Plugin/CookiePlugin.php
+++ b/src/Plugin/CookiePlugin.php
@@ -1,5 +1,7 @@
cookieJar = $cookieJar;
@@ -36,7 +36,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) {
@@ -91,19 +91,16 @@ public function handleRequest(RequestInterface $request, callable $next, callabl
/**
* Creates a cookie from a string.
*
- * @param RequestInterface $request
- * @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;
+ return null;
}
list($name, $cookieValue) = $this->createValueKey(array_shift($parts));
@@ -170,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 0239d40..271ad3c 100644
--- a/src/Plugin/DecoderPlugin.php
+++ b/src/Plugin/DecoderPlugin.php
@@ -1,9 +1,12 @@
decodeOnEncodingHeader('Transfer-Encoding', $response);
@@ -83,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);
@@ -120,12 +114,9 @@ private function decodeOnEncodingHeader($headerName, ResponseInterface $response
/**
* Decorate a stream given an encoding.
*
- * @param string $encoding
- * @param StreamInterface $stream
- *
* @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);
diff --git a/src/Plugin/ErrorPlugin.php b/src/Plugin/ErrorPlugin.php
index bcc1c67..2d1d2f1 100644
--- a/src/Plugin/ErrorPlugin.php
+++ b/src/Plugin/ErrorPlugin.php
@@ -1,10 +1,13 @@
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..95ea673 100644
--- a/src/Plugin/HeaderAppendPlugin.php
+++ b/src/Plugin/HeaderAppendPlugin.php
@@ -1,8 +1,11 @@
headers as $header => $headerValue) {
$request = $request->withAddedHeader($header, $headerValue);
diff --git a/src/Plugin/HeaderDefaultsPlugin.php b/src/Plugin/HeaderDefaultsPlugin.php
index 6dfc111..bf58070 100644
--- a/src/Plugin/HeaderDefaultsPlugin.php
+++ b/src/Plugin/HeaderDefaultsPlugin.php
@@ -1,8 +1,11 @@
headers as $header => $headerValue) {
if (!$request->hasHeader($header)) {
diff --git a/src/Plugin/HeaderRemovePlugin.php b/src/Plugin/HeaderRemovePlugin.php
index fc9c19d..9f4ca44 100644
--- a/src/Plugin/HeaderRemovePlugin.php
+++ b/src/Plugin/HeaderRemovePlugin.php
@@ -1,8 +1,11 @@
headers as $header) {
if ($request->hasHeader($header)) {
diff --git a/src/Plugin/HeaderSetPlugin.php b/src/Plugin/HeaderSetPlugin.php
index 75f11d4..06f00eb 100644
--- a/src/Plugin/HeaderSetPlugin.php
+++ b/src/Plugin/HeaderSetPlugin.php
@@ -1,8 +1,11 @@
headers as $header => $headerValue) {
$request = $request->withHeader($header, $headerValue);
diff --git a/src/Plugin/HistoryPlugin.php b/src/Plugin/HistoryPlugin.php
index 5abddbd..a147d2e 100644
--- a/src/Plugin/HistoryPlugin.php
+++ b/src/Plugin/HistoryPlugin.php
@@ -1,9 +1,12 @@
journal = $journal;
@@ -32,7 +32,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/Journal.php b/src/Plugin/Journal.php
index 15f3095..46f0a7b 100644
--- a/src/Plugin/Journal.php
+++ b/src/Plugin/Journal.php
@@ -1,5 +1,7 @@
getUri();
diff --git a/src/Plugin/RedirectPlugin.php b/src/Plugin/RedirectPlugin.php
index d2f442e..e562553 100644
--- a/src/Plugin/RedirectPlugin.php
+++ b/src/Plugin/RedirectPlugin.php
@@ -1,11 +1,14 @@
*/
-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'],
@@ -78,26 +81,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 {
@@ -131,7 +134,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)) {
@@ -142,7 +145,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)) {
@@ -170,7 +173,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl
];
}
- // Call redirect request in synchrone
+ // Call redirect request synchronously
$redirectPromise = $first($redirectRequest);
return $redirectPromise->wait();
@@ -186,7 +189,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);
@@ -215,10 +218,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 5f72b02..fdf9377 100644
--- a/src/Plugin/RequestMatcherPlugin.php
+++ b/src/Plugin/RequestMatcherPlugin.php
@@ -1,9 +1,12 @@
requestMatcher = $requestMatcher;
@@ -36,7 +35,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 3d09265..5292ddf 100644
--- a/src/Plugin/RetryPlugin.php
+++ b/src/Plugin/RetryPlugin.php
@@ -1,9 +1,13 @@
setDefaults([
'retries' => 1,
'exception_decider' => function (RequestInterface $request, Exception $e) {
- return true;
+ // do not retry client errors
+ return !$e instanceof HttpException || $e->getCode() >= 500;
},
'exception_delay' => __CLASS__.'::defaultDelay',
]);
@@ -89,7 +94,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);
@@ -117,7 +122,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl
$time = call_user_func($this->exceptionDelay, $request, $exception, $this->retryStorage[$chainIdentifier]);
usleep($time);
- // Retry in synchrone
+ // Retry synchronously
++$this->retryStorage[$chainIdentifier];
$promise = $this->handleRequest($request, $next, $first);
@@ -126,9 +131,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/Plugin/VersionBridgePlugin.php b/src/Plugin/VersionBridgePlugin.php
index f3891e5..0a2c714 100644
--- a/src/Plugin/VersionBridgePlugin.php
+++ b/src/Plugin/VersionBridgePlugin.php
@@ -1,7 +1,10 @@
doHandleRequest($request, $next, $first);
}
diff --git a/src/PluginClient.php b/src/PluginClient.php
index 8cedcf6..696d3ef 100644
--- a/src/PluginClient.php
+++ b/src/PluginClient.php
@@ -1,5 +1,7 @@
client = $client;
- } elseif ($client instanceof HttpClient || $client instanceof ClientInterface) {
+ } 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;
@@ -68,7 +70,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)) {
@@ -102,35 +104,15 @@ public function sendAsyncRequest(RequestInterface $request)
/**
* Configure the plugin client.
- *
- * @param array $options
- *
- * @return array
*/
- private function configure(array $options = [])
+ private function configure(array $options = []): array
{
- 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);
}
@@ -140,23 +122,12 @@ 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;
- /*
- * 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);
};
diff --git a/src/PluginClientFactory.php b/src/PluginClientFactory.php
index cbea3e1..6ae5091 100644
--- a/src/PluginClientFactory.php
+++ b/src/PluginClientFactory.php
@@ -1,9 +1,10 @@
doSendRequest($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);
+ }
+}
diff --git a/tests/PluginClientTest.php b/tests/PluginClientTest.php
new file mode 100644
index 0000000..eb55685
--- /dev/null
+++ b/tests/PluginClientTest.php
@@ -0,0 +1,79 @@
+assertInstanceOf($returnType, $result);
+ }
+
+ 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);
+ }
+ $this->firstRun = true;
+
+ 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];
+ }
+}