2
2
3
3
namespace Http \Client \Plugin ;
4
4
5
- use Http \Client \Common \EmulatedHttpAsyncClient ;
6
- use Http \Client \Exception ;
7
5
use Http \Client \HttpAsyncClient ;
8
6
use Http \Client \HttpClient ;
9
7
use Http \Client \Plugin \Exception \LoopException ;
10
- use Http \Promise \FulfilledPromise ;
11
- use Http \Promise \RejectedPromise ;
12
8
use Psr \Http \Message \RequestInterface ;
13
- use Symfony \Component \OptionsResolver \OptionsResolver ;
14
9
15
10
/**
16
11
* The client managing plugins and providing a decorator around HTTP Clients.
22
17
final class PluginClient implements HttpClient, HttpAsyncClient
23
18
{
24
19
/**
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
42
21
*/
43
- private $ options ;
22
+ private $ pluginClient ;
44
23
45
24
/**
46
25
* @param HttpClient|HttpAsyncClient $client
@@ -54,101 +33,30 @@ final class PluginClient implements HttpClient, HttpAsyncClient
54
33
*/
55
34
public function __construct ($ client , array $ plugins = [], array $ options = [])
56
35
{
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 );
67
37
}
68
38
69
39
/**
70
40
* {@inheritdoc}
71
41
*/
72
42
public function sendRequest (RequestInterface $ request )
73
43
{
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 );
77
48
}
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 ();
90
49
}
91
50
92
51
/**
93
52
* {@inheritdoc}
94
53
*/
95
54
public function sendAsyncRequest (RequestInterface $ request )
96
55
{
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 );
139
60
}
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 ;
153
61
}
154
62
}
0 commit comments