1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of Guzzle HTTP JSON-RPC |
5
|
|
|
* |
6
|
|
|
* Copyright (c) 2014 Nature Delivered Ltd. <http://graze.com> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
* |
11
|
|
|
* @see http://github.com/graze/guzzle-jsonrpc/blob/master/LICENSE |
12
|
|
|
* @link http://github.com/graze/guzzle-jsonrpc |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace Graze\GuzzleHttp\JsonRpc; |
16
|
|
|
|
17
|
|
|
use Graze\GuzzleHttp\JsonRpc; |
18
|
|
|
use Graze\GuzzleHttp\JsonRpc\Message\MessageFactory; |
19
|
|
|
use Graze\GuzzleHttp\JsonRpc\Message\MessageFactoryInterface; |
20
|
|
|
use Graze\GuzzleHttp\JsonRpc\Message\RequestInterface; |
21
|
|
|
use Graze\GuzzleHttp\JsonRpc\Message\ResponseInterface; |
22
|
|
|
use Graze\GuzzleHttp\JsonRpc\Middleware\RequestFactoryMiddleware; |
23
|
|
|
use Graze\GuzzleHttp\JsonRpc\Middleware\RequestHeaderMiddleware; |
24
|
|
|
use Graze\GuzzleHttp\JsonRpc\Middleware\ResponseFactoryMiddleware; |
25
|
|
|
use Graze\GuzzleHttp\JsonRpc\Middleware\RpcErrorMiddleware; |
26
|
|
|
use GuzzleHttp\Client as HttpClient; |
27
|
|
|
use GuzzleHttp\ClientInterface as HttpClientInterface; |
28
|
|
|
use GuzzleHttp\Promise\PromiseInterface; |
29
|
|
|
|
30
|
|
|
class Client implements ClientInterface |
31
|
|
|
{ |
32
|
|
|
/** |
33
|
|
|
* @var HttpClientInterface |
34
|
|
|
*/ |
35
|
|
|
protected $httpClient; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var MessageFactoryInterface |
39
|
|
|
*/ |
40
|
|
|
protected $messageFactory; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @param HttpClientInterface $httpClient |
44
|
|
|
* @param MessageFactoryInterface $factory |
45
|
|
|
*/ |
46
|
13 |
|
public function __construct(HttpClientInterface $httpClient, MessageFactoryInterface $factory) |
47
|
|
|
{ |
48
|
13 |
|
$this->httpClient = $httpClient; |
49
|
13 |
|
$this->messageFactory = $factory; |
50
|
|
|
|
51
|
13 |
|
$handler = $this->httpClient->getConfig('handler'); |
52
|
13 |
|
$handler->push(new RequestFactoryMiddleware($factory)); |
53
|
13 |
|
$handler->push(new RequestHeaderMiddleware()); |
54
|
13 |
|
$handler->push(new RpcErrorMiddleware()); |
55
|
13 |
|
$handler->push(new ResponseFactoryMiddleware($factory)); |
56
|
13 |
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @param string $uri |
60
|
|
|
* @param array $config |
61
|
|
|
* |
62
|
|
|
* @return Client |
63
|
|
|
*/ |
64
|
1 |
|
public static function factory($uri, array $config = []) |
65
|
|
|
{ |
66
|
1 |
|
if (isset($config['message_factory'])) { |
67
|
|
|
$factory = $config['message_factory']; |
68
|
|
|
unset($config['message_factory']); |
69
|
|
|
} else { |
70
|
1 |
|
$factory = new MessageFactory(); |
71
|
|
|
} |
72
|
|
|
|
73
|
1 |
|
return new self(new HttpClient(array_merge($config, [ |
74
|
1 |
|
'base_uri' => $uri, |
75
|
1 |
|
])), $factory); |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* {@inheritdoc} |
80
|
|
|
* |
81
|
|
|
* @link http://www.jsonrpc.org/specification#notification |
82
|
|
|
* |
83
|
|
|
* @param string $method |
84
|
|
|
* @param array|null $params |
85
|
|
|
* |
86
|
|
|
* @return RequestInterface |
87
|
|
|
*/ |
88
|
2 |
View Code Duplication |
public function notification($method, array $params = null) |
|
|
|
|
89
|
|
|
{ |
90
|
2 |
|
return $this->createRequest(RequestInterface::NOTIFICATION, array_filter([ |
91
|
2 |
|
'jsonrpc' => self::SPEC, |
92
|
2 |
|
'method' => $method, |
93
|
2 |
|
'params' => $params, |
94
|
|
|
])); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* {@inheritdoc} |
99
|
|
|
* |
100
|
|
|
* @link http://www.jsonrpc.org/specification#request_object |
101
|
|
|
* |
102
|
|
|
* @param mixed $id |
103
|
|
|
* @param string $method |
104
|
|
|
* @param array|null $params |
105
|
|
|
* |
106
|
|
|
* @return RequestInterface |
107
|
|
|
*/ |
108
|
3 |
View Code Duplication |
public function request($id, $method, array $params = null) |
|
|
|
|
109
|
|
|
{ |
110
|
3 |
|
return $this->createRequest(RequestInterface::REQUEST, array_filter([ |
111
|
3 |
|
'jsonrpc' => self::SPEC, |
112
|
3 |
|
'method' => $method, |
113
|
3 |
|
'params' => $params, |
114
|
3 |
|
'id' => $id, |
115
|
|
|
])); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* {@inheritdoc} |
120
|
|
|
* |
121
|
|
|
* @param RequestInterface $request |
122
|
|
|
* |
123
|
|
|
* @return ResponseInterface|null |
124
|
|
|
*/ |
125
|
2 |
|
public function send(RequestInterface $request) |
126
|
|
|
{ |
127
|
2 |
|
$promise = $this->sendAsync($request); |
128
|
|
|
|
129
|
2 |
|
return $promise->wait(); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* {@inheritdoc} |
134
|
|
|
* |
135
|
|
|
* @param RequestInterface $request |
136
|
|
|
* |
137
|
|
|
* @return PromiseInterface |
138
|
|
|
*/ |
139
|
4 |
|
public function sendAsync(RequestInterface $request) |
140
|
|
|
{ |
141
|
4 |
|
return $this->httpClient->sendAsync($request)->then( |
142
|
4 |
|
function (ResponseInterface $response) use ($request) { |
143
|
4 |
|
return $request->getRpcId() ? $response : null; |
144
|
4 |
|
} |
145
|
|
|
); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* {@inheritdoc} |
150
|
|
|
* |
151
|
|
|
* @link http://www.jsonrpc.org/specification#batch |
152
|
|
|
* |
153
|
|
|
* @param RequestInterface[] $requests |
154
|
|
|
* |
155
|
|
|
* @return ResponseInterface[] |
156
|
|
|
*/ |
157
|
1 |
|
public function sendAll(array $requests) |
158
|
|
|
{ |
159
|
1 |
|
$promise = $this->sendAllAsync($requests); |
160
|
|
|
|
161
|
1 |
|
return $promise->wait(); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* {@inheritdoc} |
166
|
|
|
* |
167
|
|
|
* @link http://www.jsonrpc.org/specification#batch |
168
|
|
|
* |
169
|
|
|
* @param RequestInterface[] $requests |
170
|
|
|
* |
171
|
|
|
* @return PromiseInterface |
172
|
|
|
*/ |
173
|
2 |
|
public function sendAllAsync(array $requests) |
174
|
|
|
{ |
175
|
2 |
|
return $this->httpClient->sendAsync($this->createRequest( |
176
|
2 |
|
RequestInterface::BATCH, |
177
|
2 |
|
$this->getBatchRequestOptions($requests) |
178
|
2 |
|
))->then(function (ResponseInterface $response) { |
179
|
2 |
|
return $this->getBatchResponses($response); |
180
|
2 |
|
}); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* @param string $method |
185
|
|
|
* @param array $options |
186
|
|
|
* |
187
|
|
|
* @return RequestInterface |
188
|
|
|
*/ |
189
|
7 |
|
protected function createRequest($method, array $options) |
190
|
|
|
{ |
191
|
7 |
|
$uri = $this->httpClient->getConfig('base_uri'); |
192
|
7 |
|
$defaults = $this->httpClient->getConfig('defaults'); |
193
|
7 |
|
$headers = isset($defaults['headers']) ? $defaults['headers'] : []; |
194
|
|
|
|
195
|
7 |
|
return $this->messageFactory->createRequest($method, $uri, $headers, $options); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* @param RequestInterface[] $requests |
200
|
|
|
* |
201
|
|
|
* @return array |
202
|
|
|
*/ |
203
|
|
|
protected function getBatchRequestOptions(array $requests) |
204
|
|
|
{ |
205
|
2 |
|
return array_map(function (RequestInterface $request) { |
206
|
2 |
|
return JsonRpc\json_decode((string) $request->getBody()); |
207
|
2 |
|
}, $requests); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* @param ResponseInterface $response |
212
|
|
|
* |
213
|
|
|
* @return ResponseInterface[] |
214
|
|
|
*/ |
215
|
2 |
|
protected function getBatchResponses(ResponseInterface $response) |
216
|
|
|
{ |
217
|
2 |
|
$results = JsonRpc\json_decode((string) $response->getBody(), true); |
218
|
|
|
|
219
|
2 |
|
return array_map(function (array $result) use ($response) { |
220
|
2 |
|
return $this->messageFactory->createResponse( |
221
|
2 |
|
$response->getStatusCode(), |
222
|
2 |
|
$response->getHeaders(), |
223
|
2 |
|
$result |
224
|
|
|
); |
225
|
2 |
|
}, $results); |
226
|
|
|
} |
227
|
|
|
} |
228
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.