22
33namespace Http \Client \Plugin ;
44
5- use Http \Client \Common \EmulatedHttpAsyncClient ;
6- use Http \Client \Exception ;
75use Http \Client \HttpAsyncClient ;
86use Http \Client \HttpClient ;
97use Http \Client \Plugin \Exception \LoopException ;
10- use Http \Promise \FulfilledPromise ;
11- use Http \Promise \RejectedPromise ;
128use Psr \Http \Message \RequestInterface ;
13- use Symfony \Component \OptionsResolver \OptionsResolver ;
149
1510/**
1611 * The client managing plugins and providing a decorator around HTTP Clients.
2217final class PluginClient implements HttpClient, HttpAsyncClient
2318{
2419 /**
25- * An HTTP async client.
26- *
27- * @var HttpAsyncClient
28- */
29- private $ client ;
30-
31- /**
32- * The plugin chain.
33- *
34- * @var Plugin[]
35- */
36- private $ plugins ;
37-
38- /**
39- * A list of options.
40- *
41- * @var array
20+ * @var \Http\Client\Common\PluginClient
4221 */
43- private $ options ;
22+ private $ pluginClient ;
4423
4524 /**
4625 * @param HttpClient|HttpAsyncClient $client
@@ -54,101 +33,30 @@ final class PluginClient implements HttpClient, HttpAsyncClient
5433 */
5534 public function __construct ($ client , array $ plugins = [], array $ options = [])
5635 {
57- if ($ client instanceof HttpAsyncClient) {
58- $ this ->client = $ client ;
59- } elseif ($ client instanceof HttpClient) {
60- $ this ->client = new EmulatedHttpAsyncClient ($ client );
61- } else {
62- throw new \RuntimeException ('Client must be an instance of Http \\Client \\HttpClient or Http \\Client \\HttpAsyncClient ' );
63- }
64-
65- $ this ->plugins = $ plugins ;
66- $ this ->options = $ this ->configure ($ options );
36+ $ this ->pluginClient = new \Http \Client \Common \PluginClient ($ client , $ plugins , $ options );
6737 }
6838
6939 /**
7040 * {@inheritdoc}
7141 */
7242 public function sendRequest (RequestInterface $ request )
7343 {
74- // If we don't have an http client, use the async call
75- if (!($ this ->client instanceof HttpClient)) {
76- return $ this ->sendAsyncRequest ($ request )->wait ();
44+ try {
45+ return $ this ->pluginClient ->sendRequest ($ request );
46+ } catch (\Http \Client \Common \Exception \LoopException $ e ) {
47+ throw new LoopException ($ e ->getMessage (), $ e ->getRequest (), $ e );
7748 }
78-
79- // Else we want to use the synchronous call of the underlying client, and not the async one in the case
80- // we have both an async and sync call
81- $ pluginChain = $ this ->createPluginChain ($ this ->plugins , function (RequestInterface $ request ) {
82- try {
83- return new FulfilledPromise ($ this ->client ->sendRequest ($ request ));
84- } catch (Exception $ exception ) {
85- return new RejectedPromise ($ exception );
86- }
87- });
88-
89- return $ pluginChain ($ request )->wait ();
9049 }
9150
9251 /**
9352 * {@inheritdoc}
9453 */
9554 public function sendAsyncRequest (RequestInterface $ request )
9655 {
97- $ pluginChain = $ this ->createPluginChain ($ this ->plugins , function (RequestInterface $ request ) {
98- return $ this ->client ->sendAsyncRequest ($ request );
99- });
100-
101- return $ pluginChain ($ request );
102- }
103-
104- /**
105- * Configure the plugin client.
106- *
107- * @param array $options
108- *
109- * @return array
110- */
111- private function configure (array $ options = [])
112- {
113- $ resolver = new OptionsResolver ();
114- $ resolver ->setDefaults ([
115- 'max_restarts ' => 10 ,
116- ]);
117-
118- return $ resolver ->resolve ($ options );
119- }
120-
121- /**
122- * Create the plugin chain.
123- *
124- * @param Plugin[] $pluginList A list of plugins
125- * @param callable $clientCallable Callable making the HTTP call
126- *
127- * @return callable
128- */
129- private function createPluginChain ($ pluginList , callable $ clientCallable )
130- {
131- $ firstCallable = $ lastCallable = $ clientCallable ;
132-
133- while ($ plugin = array_pop ($ pluginList )) {
134- $ lastCallable = function (RequestInterface $ request ) use ($ plugin , $ lastCallable , &$ firstCallable ) {
135- return $ plugin ->handleRequest ($ request , $ lastCallable , $ firstCallable );
136- };
137-
138- $ firstCallable = $ lastCallable ;
56+ try {
57+ return $ this ->pluginClient ->sendAsyncRequest ($ request );
58+ } catch (\Http \Client \Common \Exception \LoopException $ e ) {
59+ throw new LoopException ($ e ->getMessage (), $ e ->getRequest (), $ e );
13960 }
140-
141- $ firstCalls = 0 ;
142- $ firstCallable = function (RequestInterface $ request ) use ($ lastCallable , &$ firstCalls ) {
143- if ($ firstCalls > $ this ->options ['max_restarts ' ]) {
144- throw new LoopException ('Too many restarts in plugin client ' , $ request );
145- }
146-
147- ++$ firstCalls ;
148-
149- return $ lastCallable ($ request );
150- };
151-
152- return $ firstCallable ;
15361 }
15462}
0 commit comments