From 71e787d624208cebe9d47abab3c3d53f30a69135 Mon Sep 17 00:00:00 2001 From: David Buchmann Date: Sun, 2 Dec 2018 09:11:06 +0100 Subject: [PATCH] mark classes as final and methods and properties as private --- CHANGELOG.md | 3 + ...ClientSpec.php => BatchClientImplSpec.php} | 6 +- .../HttpClientPoolItemImplSpec.php} | 4 +- .../LeastUsedClientPoolSpec.php | 5 +- spec/HttpClientPool/RandomClientPoolSpec.php | 4 +- .../RoundRobinClientPoolSpec.php | 4 +- ...rSpec.php => HttpClientRouterImplSpec.php} | 10 +- spec/HttpMethodsClientImplSpec.php | 89 ++++++++++++ spec/HttpMethodsClientSpec.php | 136 ------------------ src/BatchClient.php | 40 +----- src/BatchClientImpl.php | 47 ++++++ src/Deferred.php | 2 +- src/EmulatedHttpAsyncClient.php | 6 +- src/EmulatedHttpClient.php | 6 +- src/HttpClientPool.php | 45 +----- src/HttpClientPool/HttpClientPool.php | 61 ++++++++ src/HttpClientPool/HttpClientPoolItem.php | 38 +++++ .../HttpClientPoolItemImpl.php} | 50 ++----- src/HttpClientPool/LeastUsedClientPool.php | 2 - src/HttpClientPool/RandomClientPool.php | 2 - src/HttpClientPool/RoundRobinClientPool.php | 2 - src/HttpClientRouter.php | 56 +------- src/HttpClientRouterImpl.php | 68 +++++++++ src/HttpMethodsClient.php | 84 ++--------- src/HttpMethodsClientImpl.php | 85 +++++++++++ 25 files changed, 450 insertions(+), 405 deletions(-) rename spec/{BatchClientSpec.php => BatchClientImplSpec.php} (88%) rename spec/{HttpClientPoolItemSpec.php => HttpClientPool/HttpClientPoolItemImplSpec.php} (98%) rename spec/{HttpClientRouterSpec.php => HttpClientRouterImplSpec.php} (88%) create mode 100644 spec/HttpMethodsClientImplSpec.php delete mode 100644 spec/HttpMethodsClientSpec.php create mode 100644 src/BatchClientImpl.php create mode 100644 src/HttpClientPool/HttpClientPool.php create mode 100644 src/HttpClientPool/HttpClientPoolItem.php rename src/{HttpClientPoolItem.php => HttpClientPool/HttpClientPoolItemImpl.php} (71%) create mode 100644 src/HttpClientRouterImpl.php create mode 100644 src/HttpMethodsClientImpl.php diff --git a/CHANGELOG.md b/CHANGELOG.md index c6a01d9..458a2dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ ### Changed - Abstract method `HttpClientPool::chooseHttpClient()` has now an explicit return type (`Http\Client\Common\HttpClientPoolItem`) - Interface method `Plugin::handleRequest(...)` has now an explicit return type (`Http\Promise\Promise`) +- Made all classes final as they are not intended to be extended. + Added interfaces for BatchClient, HttpClientPool, HttpClientRouter and HttpMethodsClient. + Those classes have been renamed with an `Impl` suffix. ### Removed - Deprecated option `debug_plugins` has been removed from `PluginClient` diff --git a/spec/BatchClientSpec.php b/spec/BatchClientImplSpec.php similarity index 88% rename from spec/BatchClientSpec.php rename to spec/BatchClientImplSpec.php index 86c6c8b..84df29f 100644 --- a/spec/BatchClientSpec.php +++ b/spec/BatchClientImplSpec.php @@ -6,16 +6,16 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use PhpSpec\ObjectBehavior; -use Http\Client\Common\BatchClient; +use Http\Client\Common\BatchClientImpl; use Http\Client\Common\BatchResult; use Http\Client\Exception\HttpException; use Http\Client\Common\Exception\BatchException; -class BatchClientSpec extends ObjectBehavior +class BatchClientImplSpec extends ObjectBehavior { public function let(HttpClient $client) { - $this->beAnInstanceOf(BatchClient::class, [$client]); + $this->beAnInstanceOf(BatchClientImpl::class, [$client]); } public function it_send_multiple_request_using_send_request(HttpClient $client, RequestInterface $request1, RequestInterface $request2, ResponseInterface $response1, ResponseInterface $response2) diff --git a/spec/HttpClientPoolItemSpec.php b/spec/HttpClientPool/HttpClientPoolItemImplSpec.php similarity index 98% rename from spec/HttpClientPoolItemSpec.php rename to spec/HttpClientPool/HttpClientPoolItemImplSpec.php index f44351b..b853e7f 100644 --- a/spec/HttpClientPoolItemSpec.php +++ b/spec/HttpClientPool/HttpClientPoolItemImplSpec.php @@ -1,6 +1,6 @@ addHttpClient(new HttpClientPoolItem($client->getWrappedObject(), 0)); + $this->addHttpClient(new HttpClientPoolItemImpl($client->getWrappedObject(), 0)); $client->sendRequest($request)->willThrow(HttpException::class); $this->shouldThrow(HttpException::class)->duringSendRequest($request); diff --git a/spec/HttpClientPool/RandomClientPoolSpec.php b/spec/HttpClientPool/RandomClientPoolSpec.php index fb0e5ad..a7e6c62 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\HttpClientPoolItemImpl; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; use Http\Promise\Promise; @@ -65,7 +65,7 @@ public function it_throw_exception_if_no_more_enable_client(HttpClient $client, public function it_reenable_client(HttpClient $client, RequestInterface $request) { - $this->addHttpClient(new HttpClientPoolItem($client->getWrappedObject(), 0)); + $this->addHttpClient(new HttpClientPoolItemImpl($client->getWrappedObject(), 0)); $client->sendRequest($request)->willThrow(HttpException::class); $this->shouldThrow(HttpException::class)->duringSendRequest($request); diff --git a/spec/HttpClientPool/RoundRobinClientPoolSpec.php b/spec/HttpClientPool/RoundRobinClientPoolSpec.php index 925f548..e64239b 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\HttpClientPoolItemImpl; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; use Http\Promise\Promise; @@ -65,7 +65,7 @@ public function it_throw_exception_if_no_more_enable_client(HttpClient $client, public function it_reenable_client(HttpClient $client, RequestInterface $request) { - $this->addHttpClient(new HttpClientPoolItem($client->getWrappedObject(), 0)); + $this->addHttpClient(new HttpClientPoolItemImpl($client->getWrappedObject(), 0)); $client->sendRequest($request)->willThrow(HttpException::class); $this->shouldThrow(HttpException::class)->duringSendRequest($request); diff --git a/spec/HttpClientRouterSpec.php b/spec/HttpClientRouterImplSpec.php similarity index 88% rename from spec/HttpClientRouterSpec.php rename to spec/HttpClientRouterImplSpec.php index 68446a4..afb0591 100644 --- a/spec/HttpClientRouterSpec.php +++ b/spec/HttpClientRouterImplSpec.php @@ -2,6 +2,7 @@ namespace spec\Http\Client\Common; +use Http\Client\Common\HttpClientRouterImpl; use Http\Message\RequestMatcher; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; @@ -12,11 +13,16 @@ use Http\Client\Common\HttpClientRouter; use Http\Client\Exception\RequestException; -class HttpClientRouterSpec extends ObjectBehavior +class HttpClientRouterImplSpec extends ObjectBehavior { public function it_is_initializable() { - $this->shouldHaveType(HttpClientRouter::class); + $this->shouldHaveType(HttpClientRouterImpl::class); + } + + public function it_is_an_http_client_router() + { + $this->shouldImplement(HttpClientRouter::class); } public function it_is_an_http_client() diff --git a/spec/HttpMethodsClientImplSpec.php b/spec/HttpMethodsClientImplSpec.php new file mode 100644 index 0000000..8ca90ab --- /dev/null +++ b/spec/HttpMethodsClientImplSpec.php @@ -0,0 +1,89 @@ + '/uri', + 'headers' => [ + 'Content-Type' => 'text/plain', + ], + 'body' => 'body', + ]; + + public function let(HttpClient $client, RequestFactory $requestFactory) + { + $this->beAnInstanceOf( + HttpMethodsClientImpl::class, [ + $client, + $requestFactory, + ] + ); + } + + public function it_sends_a_get_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) + { + $this->assert($client, $requestFactory, $request, $response, 'get'); + } + + public function it_sends_a_head_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) + { + $this->assert($client, $requestFactory, $request, $response, 'head'); + } + + public function it_sends_a_trace_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) + { + $this->assert($client, $requestFactory, $request, $response, 'trace'); + } + + public function it_sends_a_post_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) + { + $this->assert($client, $requestFactory, $request, $response, 'post', self::$requestData['body']); + } + + public function it_sends_a_put_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) + { + $this->assert($client, $requestFactory, $request, $response, 'put', self::$requestData['body']); + } + + public function it_sends_a_patch_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) + { + $this->assert($client, $requestFactory, $request, $response, 'patch', self::$requestData['body']); + } + + public function it_sends_a_delete_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) + { + $this->assert($client, $requestFactory, $request, $response, 'delete', self::$requestData['body']); + } + + public function it_sends_an_options_request(HttpClient $client, RequestFactory $requestFactory, RequestInterface $request, ResponseInterface $response) + { + $this->assert($client, $requestFactory, $request, $response, 'options', self::$requestData['body']); + } + + /** + * 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->$method(self::$requestData['uri'], self::$requestData['headers'], self::$requestData['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); + } + + private function mockFactory(RequestFactory $requestFactory, RequestInterface $request, string $method, string $body = null) + { + $requestFactory->createRequest($method, self::$requestData['uri'], self::$requestData['headers'], $body)->willReturn($request); + } +} diff --git a/spec/HttpMethodsClientSpec.php b/spec/HttpMethodsClientSpec.php deleted file mode 100644 index 74e0810..0000000 --- a/spec/HttpMethodsClientSpec.php +++ /dev/null @@ -1,136 +0,0 @@ -beAnInstanceOf( - HttpMethodsClientStub::class, [ - $client, - $messageFactory, - ] - ); - } - - public function it_sends_a_get_request() - { - $data = HttpMethodsClientStub::$requestData; - - $this->get($data['uri'], $data['headers'])->shouldReturnAnInstanceOf(ResponseInterface::class); - } - - public function it_sends_a_head_request() - { - $data = HttpMethodsClientStub::$requestData; - - $this->head($data['uri'], $data['headers'])->shouldReturnAnInstanceOf(ResponseInterface::class); - } - - public function it_sends_a_trace_request() - { - $data = HttpMethodsClientStub::$requestData; - - $this->trace($data['uri'], $data['headers'])->shouldReturnAnInstanceOf(ResponseInterface::class); - } - - public function it_sends_a_post_request() - { - $data = HttpMethodsClientStub::$requestData; - - $this->post($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); - } - - public function it_sends_a_put_request() - { - $data = HttpMethodsClientStub::$requestData; - - $this->put($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); - } - - public function it_sends_a_patch_request() - { - $data = HttpMethodsClientStub::$requestData; - - $this->patch($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); - } - - public function it_sends_a_delete_request() - { - $data = HttpMethodsClientStub::$requestData; - - $this->delete($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); - } - - public function it_sends_a_options_request() - { - $data = HttpMethodsClientStub::$requestData; - - $this->options($data['uri'], $data['headers'], $data['body'])->shouldReturnAnInstanceOf(ResponseInterface::class); - } - - public function it_sends_request_with_underlying_client(HttpClient $client, MessageFactory $messageFactory, RequestInterface $request, ResponseInterface $response) - { - $client->sendRequest($request)->shouldBeCalled()->willReturn($response); - - $this->beConstructedWith($client, $messageFactory); - $this->sendRequest($request)->shouldReturn($response); - } -} - -class HttpMethodsClientStub extends HttpMethodsClient -{ - public static $requestData = [ - 'uri' => '/uri', - 'headers' => [ - 'Content-Type' => 'text/plain', - ], - 'body' => 'body', - ]; - - /** - * {@inheritdoc} - */ - public function send($method, $uri, array $headers = [], $body = null): ResponseInterface - { - if ($uri !== self::$requestData['uri']) { - throw new \InvalidArgumentException('Invalid URI: '.$uri); - } - - if ($headers !== self::$requestData['headers']) { - throw new \InvalidArgumentException('Invalid headers: '.print_r($headers, true)); - } - - switch ($method) { - case 'GET': - case 'HEAD': - case 'TRACE': - if (null !== $body) { - throw new \InvalidArgumentException('Non-empty body'); - } - - return new Response(); - case 'POST': - case 'PUT': - case 'PATCH': - case 'DELETE': - case 'OPTIONS': - if ($body !== self::$requestData['body']) { - throw new \InvalidArgumentException('Invalid body: '.print_r($body, true)); - } - - return new Response(); - default: - throw new \InvalidArgumentException('Invalid method: '.$method); - } - } -} diff --git a/src/BatchClient.php b/src/BatchClient.php index 8dfeb81..2925b58 100644 --- a/src/BatchClient.php +++ b/src/BatchClient.php @@ -15,26 +15,8 @@ * * @author Joel Wurtz */ -class BatchClient implements HttpClient +interface BatchClient extends HttpClient { - /** - * @var HttpClient - */ - private $client; - - public function __construct(HttpClient $client) - { - $this->client = $client; - } - - /** - * {@inheritdoc} - */ - public function sendRequest(RequestInterface $request): ResponseInterface - { - return $this->client->sendRequest($request); - } - /** * Send several requests. * @@ -49,23 +31,5 @@ public function sendRequest(RequestInterface $request): ResponseInterface * BatchResult with a map of request to result for success, request to * exception for failures */ - public function sendRequests(array $requests): BatchResult - { - $batchResult = new BatchResult(); - - foreach ($requests as $request) { - try { - $response = $this->sendRequest($request); - $batchResult = $batchResult->addResponse($request, $response); - } catch (Exception $e) { - $batchResult = $batchResult->addException($request, $e); - } - } - - if ($batchResult->hasExceptions()) { - throw new BatchException($batchResult); - } - - return $batchResult; - } + public function sendRequests(array $requests): BatchResult; } diff --git a/src/BatchClientImpl.php b/src/BatchClientImpl.php new file mode 100644 index 0000000..dbf78ee --- /dev/null +++ b/src/BatchClientImpl.php @@ -0,0 +1,47 @@ +client = $client; + } + + public function sendRequest(RequestInterface $request): ResponseInterface + { + return $this->client->sendRequest($request); + } + + public function sendRequests(array $requests): BatchResult + { + $batchResult = new BatchResult(); + + foreach ($requests as $request) { + try { + $response = $this->sendRequest($request); + $batchResult = $batchResult->addResponse($request, $response); + } catch (Exception $e) { + $batchResult = $batchResult->addException($request, $e); + } + } + + if ($batchResult->hasExceptions()) { + throw new BatchException($batchResult); + } + + return $batchResult; + } +} diff --git a/src/Deferred.php b/src/Deferred.php index 7413451..c294a8d 100644 --- a/src/Deferred.php +++ b/src/Deferred.php @@ -9,7 +9,7 @@ /** * A deferred allow to return a promise which has not been resolved yet. */ -class Deferred implements Promise +final class Deferred implements Promise { private $value; diff --git a/src/EmulatedHttpAsyncClient.php b/src/EmulatedHttpAsyncClient.php index 64acd59..9d6c557 100644 --- a/src/EmulatedHttpAsyncClient.php +++ b/src/EmulatedHttpAsyncClient.php @@ -6,13 +6,11 @@ use Http\Client\HttpClient; /** - * Emulates an async HTTP client. - * - * This should be replaced by an anonymous class in PHP 7. + * Emulates an async HTTP client with the help of a synchronous client. * * @author Márk Sági-Kazár */ -class EmulatedHttpAsyncClient implements HttpClient, HttpAsyncClient +final class EmulatedHttpAsyncClient implements HttpClient, HttpAsyncClient { use HttpAsyncClientEmulator; use HttpClientDecorator; diff --git a/src/EmulatedHttpClient.php b/src/EmulatedHttpClient.php index 3635e9f..d99b4e4 100644 --- a/src/EmulatedHttpClient.php +++ b/src/EmulatedHttpClient.php @@ -6,13 +6,11 @@ use Http\Client\HttpClient; /** - * Emulates an HTTP client. - * - * This should be replaced by an anonymous class in PHP 7. + * Emulates a synchronous HTTP client with the help of an asynchronous client. * * @author Márk Sági-Kazár */ -class EmulatedHttpClient implements HttpClient, HttpAsyncClient +final class EmulatedHttpClient implements HttpClient, HttpAsyncClient { use HttpAsyncClientDecorator; use HttpClientEmulator; diff --git a/src/HttpClientPool.php b/src/HttpClientPool.php index 90a8464..a730f50 100644 --- a/src/HttpClientPool.php +++ b/src/HttpClientPool.php @@ -2,59 +2,20 @@ namespace Http\Client\Common; -use Http\Client\Common\Exception\HttpClientNotFoundException; +use Http\Client\Common\HttpClientPool\HttpClientPoolItem; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; /** * A http client pool allows to send requests on a pool of different http client using a specific strategy (least used, * round robin, ...). */ -abstract class HttpClientPool implements HttpAsyncClient, HttpClient +interface HttpClientPool extends HttpAsyncClient, HttpClient { - /** - * @var HttpClientPoolItem[] - */ - protected $clientPool = []; - /** * Add a client to the pool. * * @param HttpClient|HttpAsyncClient|HttpClientPoolItem $client */ - public function addHttpClient($client) - { - if (!$client instanceof HttpClientPoolItem) { - $client = new HttpClientPoolItem($client); - } - - $this->clientPool[] = $client; - } - - /** - * Return an http client given a specific strategy. - * - * @throws HttpClientNotFoundException When no http client has been found into the pool - * - * @return HttpClientPoolItem Return a http client that can do both sync or async - */ - abstract protected function chooseHttpClient(): HttpClientPoolItem; - - /** - * {@inheritdoc} - */ - public function sendAsyncRequest(RequestInterface $request) - { - return $this->chooseHttpClient()->sendAsyncRequest($request); - } - - /** - * {@inheritdoc} - */ - public function sendRequest(RequestInterface $request): ResponseInterface - { - return $this->chooseHttpClient()->sendRequest($request); - } + public function addHttpClient($client); } diff --git a/src/HttpClientPool/HttpClientPool.php b/src/HttpClientPool/HttpClientPool.php new file mode 100644 index 0000000..36be0aa --- /dev/null +++ b/src/HttpClientPool/HttpClientPool.php @@ -0,0 +1,61 @@ +clientPool[] = $client; + } + + /** + * Return an http client given a specific strategy. + * + * @throws HttpClientNotFoundException When no http client has been found into the pool + * + * @return HttpClientPoolItem Return a http client that can do both sync or async + */ + abstract protected function chooseHttpClient(): HttpClientPoolItem; + + /** + * {@inheritdoc} + */ + public function sendAsyncRequest(RequestInterface $request) + { + return $this->chooseHttpClient()->sendAsyncRequest($request); + } + + /** + * {@inheritdoc} + */ + public function sendRequest(RequestInterface $request): ResponseInterface + { + return $this->chooseHttpClient()->sendRequest($request); + } +} diff --git a/src/HttpClientPool/HttpClientPoolItem.php b/src/HttpClientPool/HttpClientPoolItem.php new file mode 100644 index 0000000..ef1b7c1 --- /dev/null +++ b/src/HttpClientPool/HttpClientPoolItem.php @@ -0,0 +1,38 @@ + + */ +interface HttpClientPoolItem extends HttpClient, HttpAsyncClient +{ + /** + * Whether this client is disabled or not. + * + * Will also reactivate this client if possible + * + * @internal + * + * @return bool + */ + public function isDisabled(); + + /** + * Get current number of request that are currently being sent by the underlying HTTP client. + * + * @internal + * + * @return int + */ + public function getSendingRequestCount(); +} diff --git a/src/HttpClientPoolItem.php b/src/HttpClientPool/HttpClientPoolItemImpl.php similarity index 71% rename from src/HttpClientPoolItem.php rename to src/HttpClientPool/HttpClientPoolItemImpl.php index a46ee2f..31b9bbe 100644 --- a/src/HttpClientPoolItem.php +++ b/src/HttpClientPool/HttpClientPoolItemImpl.php @@ -1,7 +1,8 @@ */ -class HttpClientPoolItem implements HttpClient, HttpAsyncClient +final class HttpClientPoolItemImpl implements HttpClientPoolItem { /** * @var int Number of request this client is currently sending @@ -29,7 +27,11 @@ class HttpClientPoolItem implements HttpClient, HttpAsyncClient private $disabledAt; /** - * @var int|null Number of seconds after this client is reenable, by default null: never reenable this client + * Number of seconds until this client is enabled again after an error. + * + * null: never reenable this client. + * + * @var int|null */ private $reenableAfter; @@ -40,7 +42,7 @@ class HttpClientPoolItem implements HttpClient, HttpAsyncClient /** * @param HttpClient|HttpAsyncClient $client - * @param null|int $reenableAfter Number of seconds after this client is reenable + * @param null|int $reenableAfter Number of seconds until this client is enabled again after an error */ public function __construct($client, $reenableAfter = null) { @@ -95,23 +97,15 @@ public function sendAsyncRequest(RequestInterface $request) } /** - * Whether this client is disabled or not. - * - * Will also reactivate this client if possible - * - * @internal - * - * @return bool + * {@inheritdoc} */ public function isDisabled() { - $disabledAt = $this->getDisabledAt(); - - if (null !== $this->reenableAfter && null !== $disabledAt) { + if (null !== $this->reenableAfter && null !== $this->disabledAt) { // Reenable after a certain time $now = new \DateTime(); - if (($now->getTimestamp() - $disabledAt->getTimestamp()) >= $this->reenableAfter) { + if (($now->getTimestamp() - $this->disabledAt->getTimestamp()) >= $this->reenableAfter) { $this->enable(); return false; @@ -120,31 +114,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 + * {@inheritdoc} */ public function getSendingRequestCount() { return $this->sendingRequestCount; } - /** - * Return when this client has been disabled or null if it's enabled. - * - * @return \DateTime|null - */ - private function getDisabledAt() - { - return $this->disabledAt; - } - /** * Increment the request count. */ diff --git a/src/HttpClientPool/LeastUsedClientPool.php b/src/HttpClientPool/LeastUsedClientPool.php index 61eb670..e3c29b7 100644 --- a/src/HttpClientPool/LeastUsedClientPool.php +++ b/src/HttpClientPool/LeastUsedClientPool.php @@ -3,8 +3,6 @@ namespace Http\Client\Common\HttpClientPool; use Http\Client\Common\Exception\HttpClientNotFoundException; -use Http\Client\Common\HttpClientPool; -use Http\Client\Common\HttpClientPoolItem; /** * LeastUsedClientPool will choose the client with the less current request in the pool. diff --git a/src/HttpClientPool/RandomClientPool.php b/src/HttpClientPool/RandomClientPool.php index 2889ed7..3adf5fd 100644 --- a/src/HttpClientPool/RandomClientPool.php +++ b/src/HttpClientPool/RandomClientPool.php @@ -3,8 +3,6 @@ namespace Http\Client\Common\HttpClientPool; use Http\Client\Common\Exception\HttpClientNotFoundException; -use Http\Client\Common\HttpClientPool; -use Http\Client\Common\HttpClientPoolItem; /** * RoundRobinClientPool will choose the next client in the pool. diff --git a/src/HttpClientPool/RoundRobinClientPool.php b/src/HttpClientPool/RoundRobinClientPool.php index 3315b51..13cdf13 100644 --- a/src/HttpClientPool/RoundRobinClientPool.php +++ b/src/HttpClientPool/RoundRobinClientPool.php @@ -3,8 +3,6 @@ namespace Http\Client\Common\HttpClientPool; use Http\Client\Common\Exception\HttpClientNotFoundException; -use Http\Client\Common\HttpClientPool; -use Http\Client\Common\HttpClientPoolItem; /** * RoundRobinClientPool will choose the next client in the pool. diff --git a/src/HttpClientRouter.php b/src/HttpClientRouter.php index 00ca15f..403efa8 100644 --- a/src/HttpClientRouter.php +++ b/src/HttpClientRouter.php @@ -2,71 +2,23 @@ namespace Http\Client\Common; -use Http\Client\Exception\RequestException; use Http\Client\HttpAsyncClient; use Http\Client\HttpClient; use Http\Message\RequestMatcher; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; /** * Route a request to a specific client in the stack based using a RequestMatcher. * + * This is not a HttpClientPool client because it uses a matcher to select the client. + * * @author Joel Wurtz */ -final class HttpClientRouter implements HttpClient, HttpAsyncClient +interface HttpClientRouter extends HttpClient, HttpAsyncClient { - /** - * @var array - */ - private $clients = []; - - /** - * {@inheritdoc} - */ - public function sendRequest(RequestInterface $request): ResponseInterface - { - $client = $this->chooseHttpClient($request); - - return $client->sendRequest($request); - } - - /** - * {@inheritdoc} - */ - public function sendAsyncRequest(RequestInterface $request) - { - $client = $this->chooseHttpClient($request); - - return $client->sendAsyncRequest($request); - } - /** * Add a client to the router. * * @param HttpClient|HttpAsyncClient $client */ - public function addClient($client, RequestMatcher $requestMatcher) - { - $this->clients[] = [ - 'matcher' => $requestMatcher, - 'client' => new FlexibleHttpClient($client), - ]; - } - - /** - * Choose an HTTP client given a specific request. - * - * @return HttpClient|HttpAsyncClient - */ - private function chooseHttpClient(RequestInterface $request) - { - foreach ($this->clients as $client) { - if ($client['matcher']->matches($request)) { - return $client['client']; - } - } - - throw new RequestException('No client found for the specified request', $request); - } + public function addClient($client, RequestMatcher $requestMatcher); } diff --git a/src/HttpClientRouterImpl.php b/src/HttpClientRouterImpl.php new file mode 100644 index 0000000..9e11bbc --- /dev/null +++ b/src/HttpClientRouterImpl.php @@ -0,0 +1,68 @@ + + */ +final class HttpClientRouterImpl implements HttpClientRouter +{ + /** + * @var array + */ + private $clients = []; + + /** + * {@inheritdoc} + */ + public function sendRequest(RequestInterface $request): ResponseInterface + { + return $this->chooseHttpClient($request)->sendRequest($request); + } + + /** + * {@inheritdoc} + */ + public function sendAsyncRequest(RequestInterface $request) + { + return $this->chooseHttpClient($request)->sendAsyncRequest($request); + } + + /** + * Add a client to the router. + * + * @param HttpClient|HttpAsyncClient $client + */ + public function addClient($client, RequestMatcher $requestMatcher) + { + $this->clients[] = [ + 'matcher' => $requestMatcher, + 'client' => new FlexibleHttpClient($client), + ]; + } + + /** + * Choose an HTTP client given a specific request. + * + * @return HttpClient|HttpAsyncClient + */ + private function chooseHttpClient(RequestInterface $request) + { + foreach ($this->clients as $client) { + if ($client['matcher']->matches($request)) { + return $client['client']; + } + } + + throw new RequestException('No client found for the specified request', $request); + } +} diff --git a/src/HttpMethodsClient.php b/src/HttpMethodsClient.php index bc02ef8..7960d35 100644 --- a/src/HttpMethodsClient.php +++ b/src/HttpMethodsClient.php @@ -4,8 +4,6 @@ use Http\Client\Exception; use Http\Client\HttpClient; -use Http\Message\RequestFactory; -use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UriInterface; @@ -24,28 +22,8 @@ * @author Márk Sági-Kazár * @author David Buchmann */ -class HttpMethodsClient implements HttpClient +interface HttpMethodsClient extends HttpClient { - /** - * @var HttpClient - */ - private $httpClient; - - /** - * @var RequestFactory - */ - private $requestFactory; - - /** - * @param HttpClient $httpClient The client to send requests with - * @param RequestFactory $requestFactory The message factory to create requests - */ - public function __construct(HttpClient $httpClient, RequestFactory $requestFactory) - { - $this->httpClient = $httpClient; - $this->requestFactory = $requestFactory; - } - /** * Sends a GET request. * @@ -53,10 +31,7 @@ public function __construct(HttpClient $httpClient, RequestFactory $requestFacto * * @throws Exception */ - public function get($uri, array $headers = []): ResponseInterface - { - return $this->send('GET', $uri, $headers, null); - } + public function get($uri, array $headers = []): ResponseInterface; /** * Sends an HEAD request. @@ -65,10 +40,7 @@ public function get($uri, array $headers = []): ResponseInterface * * @throws Exception */ - public function head($uri, array $headers = []): ResponseInterface - { - return $this->send('HEAD', $uri, $headers, null); - } + public function head($uri, array $headers = []): ResponseInterface; /** * Sends a TRACE request. @@ -77,10 +49,7 @@ public function head($uri, array $headers = []): ResponseInterface * * @throws Exception */ - public function trace($uri, array $headers = []): ResponseInterface - { - return $this->send('TRACE', $uri, $headers, null); - } + public function trace($uri, array $headers = []): ResponseInterface; /** * Sends a POST request. @@ -90,10 +59,7 @@ public function trace($uri, array $headers = []): ResponseInterface * * @throws Exception */ - public function post($uri, array $headers = [], $body = null): ResponseInterface - { - return $this->send('POST', $uri, $headers, $body); - } + public function post($uri, array $headers = [], $body = null): ResponseInterface; /** * Sends a PUT request. @@ -103,10 +69,7 @@ public function post($uri, array $headers = [], $body = null): ResponseInterface * * @throws Exception */ - public function put($uri, array $headers = [], $body = null): ResponseInterface - { - return $this->send('PUT', $uri, $headers, $body); - } + public function put($uri, array $headers = [], $body = null): ResponseInterface; /** * Sends a PATCH request. @@ -116,10 +79,7 @@ public function put($uri, array $headers = [], $body = null): ResponseInterface * * @throws Exception */ - public function patch($uri, array $headers = [], $body = null): ResponseInterface - { - return $this->send('PATCH', $uri, $headers, $body); - } + public function patch($uri, array $headers = [], $body = null): ResponseInterface; /** * Sends a DELETE request. @@ -129,10 +89,7 @@ public function patch($uri, array $headers = [], $body = null): ResponseInterfac * * @throws Exception */ - public function delete($uri, array $headers = [], $body = null): ResponseInterface - { - return $this->send('DELETE', $uri, $headers, $body); - } + public function delete($uri, array $headers = [], $body = null): ResponseInterface; /** * Sends an OPTIONS request. @@ -142,10 +99,7 @@ public function delete($uri, array $headers = [], $body = null): ResponseInterfa * * @throws Exception */ - public function options($uri, array $headers = [], $body = null): ResponseInterface - { - return $this->send('OPTIONS', $uri, $headers, $body); - } + public function options($uri, array $headers = [], $body = null): ResponseInterface; /** * Sends a request with any HTTP method. @@ -156,23 +110,5 @@ public function options($uri, array $headers = [], $body = null): ResponseInterf * * @throws Exception */ - public function send($method, $uri, array $headers = [], $body = null): ResponseInterface - { - return $this->sendRequest($this->requestFactory->createRequest( - $method, - $uri, - $headers, - $body - )); - } - - /** - * Forward to the underlying HttpClient. - * - * {@inheritdoc} - */ - public function sendRequest(RequestInterface $request): ResponseInterface - { - return $this->httpClient->sendRequest($request); - } + public function send($method, $uri, array $headers = [], $body = null): ResponseInterface; } diff --git a/src/HttpMethodsClientImpl.php b/src/HttpMethodsClientImpl.php new file mode 100644 index 0000000..587a129 --- /dev/null +++ b/src/HttpMethodsClientImpl.php @@ -0,0 +1,85 @@ +httpClient = $httpClient; + $this->requestFactory = $requestFactory; + } + + public function get($uri, array $headers = []): ResponseInterface + { + return $this->send('GET', $uri, $headers, null); + } + + public function head($uri, array $headers = []): ResponseInterface + { + return $this->send('HEAD', $uri, $headers, null); + } + + public function trace($uri, array $headers = []): ResponseInterface + { + return $this->send('TRACE', $uri, $headers, null); + } + public function post($uri, array $headers = [], $body = null): ResponseInterface + { + return $this->send('POST', $uri, $headers, $body); + } + + public function put($uri, array $headers = [], $body = null): ResponseInterface + { + return $this->send('PUT', $uri, $headers, $body); + } + + public function patch($uri, array $headers = [], $body = null): ResponseInterface + { + return $this->send('PATCH', $uri, $headers, $body); + } + + public function delete($uri, array $headers = [], $body = null): ResponseInterface + { + return $this->send('DELETE', $uri, $headers, $body); + } + + public function options($uri, array $headers = [], $body = null): ResponseInterface + { + return $this->send('OPTIONS', $uri, $headers, $body); + } + + public function send($method, $uri, array $headers = [], $body = null): ResponseInterface + { + return $this->sendRequest($this->requestFactory->createRequest( + $method, + $uri, + $headers, + $body + )); + } + + public function sendRequest(RequestInterface $request): ResponseInterface + { + return $this->httpClient->sendRequest($request); + } +}