Skip to content

Commit 7585d59

Browse files
committed
Move the plugin client to client-common (deprecate the old one)
1 parent 741f0c4 commit 7585d59

File tree

7 files changed

+26
-225
lines changed

7 files changed

+26
-225
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"php": ">=5.4",
1515
"php-http/httplug": "^1.0",
1616
"php-http/message-factory": "^1.0.2",
17-
"php-http/client-common": "^1.0",
17+
"php-http/client-common": "dev-plugin_client",
1818
"php-http/message": "^1.0",
1919
"symfony/options-resolver": "^2.6|^3.0"
2020
},

spec/LoopPlugin.php

Lines changed: 0 additions & 14 deletions
This file was deleted.

spec/PluginClientSpec.php

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22

33
namespace spec\Http\Client\Plugin;
44

5-
use Http\Client\HttpAsyncClient;
65
use Http\Client\HttpClient;
76
use Http\Client\Plugin\Plugin;
8-
use Http\Promise\Promise;
97
use Psr\Http\Message\RequestInterface;
10-
use Psr\Http\Message\ResponseInterface;
118
use PhpSpec\ObjectBehavior;
9+
use Prophecy\Argument;
1210

1311
class PluginClientSpec extends ObjectBehavior
1412
{
@@ -32,40 +30,20 @@ function it_is_an_http_async_client()
3230
$this->shouldImplement('Http\Client\HttpAsyncClient');
3331
}
3432

35-
function it_sends_request_with_underlying_client(HttpClient $client, RequestInterface $request, ResponseInterface $response)
33+
function it_throws_loop_exception(HttpClient $client, RequestInterface $request, Plugin $plugin)
3634
{
37-
$client->sendRequest($request)->willReturn($response);
35+
$plugin
36+
->handleRequest(
37+
$request,
38+
Argument::type('callable'),
39+
Argument::type('callable')
40+
)
41+
->will(function ($args) {
42+
return $args[2]($args[0]);
43+
})
44+
;
3845

39-
$this->sendRequest($request)->shouldReturn($response);
40-
}
41-
42-
function it_sends_async_request_with_underlying_client(HttpAsyncClient $asyncClient, RequestInterface $request, Promise $promise)
43-
{
44-
$asyncClient->sendAsyncRequest($request)->willReturn($promise);
45-
46-
$this->beConstructedWith($asyncClient);
47-
$this->sendAsyncRequest($request)->shouldReturn($promise);
48-
}
49-
50-
function it_sends_async_request_if_no_send_request(HttpAsyncClient $asyncClient, RequestInterface $request, ResponseInterface $response, Promise $promise)
51-
{
52-
$this->beConstructedWith($asyncClient->getWrappedObject());
53-
$asyncClient->sendAsyncRequest($request)->willReturn($promise);
54-
$promise->wait()->willReturn($response);
55-
56-
$this->sendRequest($request)->shouldReturn($response);
57-
}
58-
59-
function it_prefers_send_request(StubClient $client, RequestInterface $request, ResponseInterface $response)
60-
{
61-
$client->sendRequest($request)->willReturn($response);
62-
63-
$this->sendRequest($request)->shouldReturn($response);
64-
}
65-
66-
function it_throws_loop_exception(HttpClient $client, RequestInterface $request)
67-
{
68-
$this->beConstructedWith($client, [new LoopPlugin()]);
46+
$this->beConstructedWith($client, [$plugin]);
6947

7048
$this->shouldThrow('Http\Client\Plugin\Exception\LoopException')->duringSendRequest($request);
7149
}

spec/StubClient.php

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/Exception/LoopException.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
namespace Http\Client\Plugin\Exception;
44

5-
use Http\Client\Exception\RequestException;
6-
75
/**
86
* @author Joel Wurtz <joel.wurtz@gmail.com>
7+
*
8+
* @deprecated since version 1.1, to be removed in 2.0. Use {@link \Http\Client\Common\Exception\LoopException} instead.
99
*/
10-
class LoopException extends RequestException
10+
class LoopException extends \Http\Client\Common\Exception\LoopException
1111
{
1212
}

src/Plugin.php

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,11 @@
22

33
namespace Http\Client\Plugin;
44

5-
use Http\Promise\Promise;
6-
use Psr\Http\Message\RequestInterface;
7-
85
/**
9-
* A plugin is a middleware to transform the request and/or the response.
10-
*
11-
* The plugin can:
12-
* - break the chain and return a response
13-
* - dispatch the request to the next middleware
14-
* - restart the request
15-
*
166
* @author Joel Wurtz <joel.wurtz@gmail.com>
7+
*
8+
* @deprecated since version 1.1, to be removed in 2.0. Use {@link \Http\Client\Common\Plugin} instead.
179
*/
18-
interface Plugin
10+
interface Plugin extends \Http\Client\Common\Plugin
1911
{
20-
/**
21-
* Handle the request and return the response coming from the next callable.
22-
*
23-
* @param RequestInterface $request
24-
* @param callable $next Next middleware in the chain, the request is passed as the first argument
25-
* @param callable $first First middleware in the chain, used to to restart a request
26-
*
27-
* @return Promise
28-
*/
29-
public function handleRequest(RequestInterface $request, callable $next, callable $first);
3012
}

src/PluginClient.php

Lines changed: 6 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -2,151 +2,24 @@
22

33
namespace Http\Client\Plugin;
44

5-
use Http\Client\Common\EmulatedHttpAsyncClient;
65
use Http\Client\Exception;
7-
use Http\Client\HttpAsyncClient;
8-
use Http\Client\HttpClient;
96
use Http\Client\Plugin\Exception\LoopException;
10-
use Http\Promise\FulfilledPromise;
11-
use Http\Promise\RejectedPromise;
127
use Psr\Http\Message\RequestInterface;
13-
use Symfony\Component\OptionsResolver\OptionsResolver;
148

159
/**
16-
* The client managing plugins and providing a decorator around HTTP Clients.
17-
*
1810
* @author Joel Wurtz <joel.wurtz@gmail.com>
11+
*
12+
* @deprecated since version 1.1, to be removed in 2.0. Use {@link \Http\Client\Common\PluginClient} instead.
1913
*/
20-
final class PluginClient implements HttpClient, HttpAsyncClient
14+
final class PluginClient extends \Http\Client\Common\PluginClient
2115
{
22-
/**
23-
* An HTTP async client.
24-
*
25-
* @var HttpAsyncClient
26-
*/
27-
private $client;
28-
29-
/**
30-
* The plugin chain.
31-
*
32-
* @var Plugin[]
33-
*/
34-
private $plugins;
35-
36-
/**
37-
* A list of options.
38-
*
39-
* @var array
40-
*/
41-
private $options;
42-
43-
/**
44-
* @param HttpClient|HttpAsyncClient $client
45-
* @param Plugin[] $plugins
46-
* @param array $options {
47-
*
48-
* @var int $max_restarts
49-
* }
50-
*
51-
* @throws \RuntimeException if client is not an instance of HttpClient or HttpAsyncClient
52-
*/
53-
public function __construct($client, array $plugins = [], array $options = [])
54-
{
55-
if ($client instanceof HttpAsyncClient) {
56-
$this->client = $client;
57-
} elseif ($client instanceof HttpClient) {
58-
$this->client = new EmulatedHttpAsyncClient($client);
59-
} else {
60-
throw new \RuntimeException('Client must be an instance of Http\\Client\\HttpClient or Http\\Client\\HttpAsyncClient');
61-
}
62-
63-
$this->plugins = $plugins;
64-
$this->options = $this->configure($options);
65-
}
66-
6716
/**
6817
* {@inheritdoc}
69-
*/
70-
public function sendRequest(RequestInterface $request)
71-
{
72-
// If we don't have an http client, use the async call
73-
if (!($this->client instanceof HttpClient)) {
74-
return $this->sendAsyncRequest($request)->wait();
75-
}
76-
77-
// Else we want to use the synchronous call of the underlying client, and not the async one in the case
78-
// we have both an async and sync call
79-
$pluginChain = $this->createPluginChain($this->plugins, function (RequestInterface $request) {
80-
try {
81-
return new FulfilledPromise($this->client->sendRequest($request));
82-
} catch (Exception $exception) {
83-
return new RejectedPromise($exception);
84-
}
85-
});
86-
87-
return $pluginChain($request)->wait();
88-
}
89-
90-
/**
91-
* {@inheritdoc}
92-
*/
93-
public function sendAsyncRequest(RequestInterface $request)
94-
{
95-
$pluginChain = $this->createPluginChain($this->plugins, function (RequestInterface $request) {
96-
return $this->client->sendAsyncRequest($request);
97-
});
98-
99-
return $pluginChain($request);
100-
}
101-
102-
/**
103-
* Configure the plugin client.
10418
*
105-
* @param array $options
106-
*
107-
* @return array
19+
* Throw the correct loop exception.
10820
*/
109-
private function configure(array $options = [])
21+
protected function createLoopException(RequestInterface $request)
11022
{
111-
$resolver = new OptionsResolver();
112-
$resolver->setDefaults([
113-
'max_restarts' => 10,
114-
]);
115-
116-
return $resolver->resolve($options);
117-
}
118-
119-
/**
120-
* Create the plugin chain.
121-
*
122-
* @param Plugin[] $pluginList A list of plugins
123-
* @param callable $clientCallable Callable making the HTTP call
124-
*
125-
* @return callable
126-
*/
127-
private function createPluginChain($pluginList, callable $clientCallable)
128-
{
129-
$firstCallable = $lastCallable = $clientCallable;
130-
131-
while ($plugin = array_pop($pluginList)) {
132-
$lastCallable = function (RequestInterface $request) use ($plugin, $lastCallable, &$firstCallable) {
133-
return $plugin->handleRequest($request, $lastCallable, $firstCallable);
134-
};
135-
136-
$firstCallable = $lastCallable;
137-
}
138-
139-
$firstCalls = 0;
140-
$firstCallable = function (RequestInterface $request) use ($lastCallable, &$firstCalls) {
141-
if ($firstCalls > $this->options['max_restarts']) {
142-
throw new LoopException('Too many restarts in plugin client', $request);
143-
}
144-
145-
++$firstCalls;
146-
147-
return $lastCallable($request);
148-
};
149-
150-
return $firstCallable;
23+
return new LoopException('Too many restarts in plugin client', $request);
15124
}
15225
}

0 commit comments

Comments
 (0)