7
7
use Http \Client \Exception ;
8
8
use Http \Client \HttpAsyncClient ;
9
9
use Http \Client \HttpClient ;
10
- use Http \Discovery \MessageFactoryDiscovery ;
11
- use Http \Discovery \StreamFactoryDiscovery ;
12
- use Http \Promise \Promise ;
10
+ use Http \Discovery \Psr17FactoryDiscovery ;
13
11
use Psr \Http \Message \RequestInterface ;
14
12
use Psr \Http \Message \ResponseFactoryInterface ;
15
13
use Psr \Http \Message \ResponseInterface ;
16
14
use Psr \Http \Message \StreamFactoryInterface ;
17
15
use Symfony \Component \OptionsResolver \OptionsResolver ;
18
16
19
17
/**
20
- * PSR-7 compatible cURL based HTTP client .
18
+ * PSR-18 and HTTPlug Async client based on lib-curl .
21
19
*
22
20
* @license http://opensource.org/licenses/MIT MIT
23
21
* @author Михаил Красильников <[email protected] >
@@ -34,7 +32,7 @@ class Client implements HttpClient, HttpAsyncClient
34
32
*
35
33
* @var array
36
34
*/
37
- private $ options ;
35
+ private $ curlOptions ;
38
36
39
37
/**
40
38
* PSR-17 response factory.
@@ -65,25 +63,19 @@ class Client implements HttpClient, HttpAsyncClient
65
63
private $ multiRunner ;
66
64
67
65
/**
68
- * Construct client.
69
- *
70
66
* @param ResponseFactoryInterface|null $responseFactory PSR-17 HTTP response factory.
71
67
* @param StreamFactoryInterface|null $streamFactory PSR-17 HTTP stream factory.
72
68
* @param array $options cURL options {@link http://php.net/curl_setopt}
73
69
*
74
70
* @throws \Http\Discovery\Exception\NotFoundException If factory discovery failed
75
- *
76
- * @since x.x $messageFactory changed to PSR-17 ResponseFactoryInterface $responseFactory.
77
- * @since x.x $streamFactory type changed to PSR-17 StreamFactoryInterface.
78
- * @since 1.0
79
71
*/
80
72
public function __construct (
81
73
ResponseFactoryInterface $ responseFactory = null ,
82
74
StreamFactoryInterface $ streamFactory = null ,
83
75
array $ options = []
84
76
) {
85
- $ this ->responseFactory = $ responseFactory; // FIXME ?: MessageFactoryDiscovery::find ();
86
- $ this ->streamFactory = $ streamFactory; // FIXME ?: StreamFactoryDiscovery::find ();
77
+ $ this ->responseFactory = $ responseFactory ?: Psr17FactoryDiscovery:: findResponseFactory ();
78
+ $ this ->streamFactory = $ streamFactory ?: Psr17FactoryDiscovery:: findStreamFactory ();
87
79
$ resolver = new OptionsResolver ();
88
80
$ resolver ->setDefaults (
89
81
[
@@ -99,7 +91,7 @@ public function __construct(
99
91
// Make sure that we accept everything that is in the options.
100
92
$ resolver ->setDefined (array_keys ($ options ));
101
93
102
- $ this ->options = $ resolver ->resolve ($ options );
94
+ $ this ->curlOptions = $ resolver ->resolve ($ options );
103
95
}
104
96
105
97
/**
@@ -113,11 +105,7 @@ public function __destruct()
113
105
}
114
106
115
107
/**
116
- * Sends a PSR-7 request and returns a PSR-7 response.
117
- *
118
- * @param RequestInterface $request
119
- *
120
- * @return ResponseInterface
108
+ * {@inheritdoc}
121
109
*
122
110
* @throws \Http\Client\Exception\NetworkException In case of network problems
123
111
* @throws \Http\Client\Exception\RequestException On invalid request
@@ -164,11 +152,7 @@ public function sendRequest(RequestInterface $request): ResponseInterface
164
152
}
165
153
166
154
/**
167
- * Sends a PSR-7 request in an asynchronous way.
168
- *
169
- * @param RequestInterface $request
170
- *
171
- * @return Promise
155
+ * {@inheritdoc}
172
156
*
173
157
* @throws \Http\Client\Exception\RequestException On invalid request
174
158
* @throws \InvalidArgumentException For invalid header names or values
@@ -198,36 +182,31 @@ public function sendAsyncRequest(RequestInterface $request)
198
182
/**
199
183
* Update cURL options for this request and hook in the response builder.
200
184
*
201
- * @param RequestInterface $request
202
- * @param ResponseBuilder $responseBuilder
203
- *
204
185
* @throws \Http\Client\Exception\RequestException On invalid request
205
186
* @throws \InvalidArgumentException For invalid header names or values
206
187
* @throws \RuntimeException If can not read body
207
- *
208
- * @return array
209
188
*/
210
- private function prepareRequestOptions (RequestInterface $ request , ResponseBuilder $ responseBuilder )
189
+ private function prepareRequestOptions (RequestInterface $ request , ResponseBuilder $ responseBuilder ): array
211
190
{
212
- $ options = $ this ->options ;
191
+ $ curlOptions = $ this ->curlOptions ;
213
192
214
193
try {
215
- $ options [CURLOPT_HTTP_VERSION ]
194
+ $ curlOptions [CURLOPT_HTTP_VERSION ]
216
195
= $ this ->getProtocolVersion ($ request ->getProtocolVersion ());
217
196
} catch (\UnexpectedValueException $ e ) {
218
197
throw new Exception \RequestException ($ e ->getMessage (), $ request );
219
198
}
220
- $ options [CURLOPT_URL ] = (string ) $ request ->getUri ();
199
+ $ curlOptions [CURLOPT_URL ] = (string ) $ request ->getUri ();
221
200
222
- $ options = $ this ->addRequestBodyOptions ($ request , $ options );
201
+ $ curlOptions = $ this ->addRequestBodyOptions ($ request , $ curlOptions );
223
202
224
- $ options [CURLOPT_HTTPHEADER ] = $ this ->createHeaders ($ request , $ options );
203
+ $ curlOptions [CURLOPT_HTTPHEADER ] = $ this ->createHeaders ($ request , $ curlOptions );
225
204
226
205
if ($ request ->getUri ()->getUserInfo ()) {
227
- $ options [CURLOPT_USERPWD ] = $ request ->getUri ()->getUserInfo ();
206
+ $ curlOptions [CURLOPT_USERPWD ] = $ request ->getUri ()->getUserInfo ();
228
207
}
229
208
230
- $ options [CURLOPT_HEADERFUNCTION ] = function ($ ch , $ data ) use ($ responseBuilder ) {
209
+ $ curlOptions [CURLOPT_HEADERFUNCTION ] = function ($ ch , $ data ) use ($ responseBuilder ) {
231
210
$ str = trim ($ data );
232
211
if ('' !== $ str ) {
233
212
if (strpos (strtolower ($ str ), 'http/ ' ) === 0 ) {
@@ -240,21 +219,17 @@ private function prepareRequestOptions(RequestInterface $request, ResponseBuilde
240
219
return strlen ($ data );
241
220
};
242
221
243
- $ options [CURLOPT_WRITEFUNCTION ] = function ($ ch , $ data ) use ($ responseBuilder ) {
222
+ $ curlOptions [CURLOPT_WRITEFUNCTION ] = function ($ ch , $ data ) use ($ responseBuilder ) {
244
223
return $ responseBuilder ->getResponse ()->getBody ()->write ($ data );
245
224
};
246
225
247
- return $ options ;
226
+ return $ curlOptions ;
248
227
}
249
228
250
229
/**
251
230
* Return cURL constant for specified HTTP version.
252
231
*
253
- * @param string $requestVersion
254
- *
255
232
* @throws \UnexpectedValueException If unsupported version requested
256
- *
257
- * @return int
258
233
*/
259
234
private function getProtocolVersion (string $ requestVersion ): int
260
235
{
@@ -275,13 +250,8 @@ private function getProtocolVersion(string $requestVersion): int
275
250
276
251
/**
277
252
* Add request body related cURL options.
278
- *
279
- * @param RequestInterface $request
280
- * @param array $options
281
- *
282
- * @return array
283
253
*/
284
- private function addRequestBodyOptions (RequestInterface $ request , array $ options ): array
254
+ private function addRequestBodyOptions (RequestInterface $ request , array $ curlOptions ): array
285
255
{
286
256
/*
287
257
* Some HTTP methods cannot have payload:
@@ -302,40 +272,37 @@ private function addRequestBodyOptions(RequestInterface $request, array $options
302
272
// Message has non empty body.
303
273
if (null === $ bodySize || $ bodySize > 1024 * 1024 ) {
304
274
// Avoid full loading large or unknown size body into memory
305
- $ options [CURLOPT_UPLOAD ] = true ;
275
+ $ curlOptions [CURLOPT_UPLOAD ] = true ;
306
276
if (null !== $ bodySize ) {
307
- $ options [CURLOPT_INFILESIZE ] = $ bodySize ;
277
+ $ curlOptions [CURLOPT_INFILESIZE ] = $ bodySize ;
308
278
}
309
- $ options [CURLOPT_READFUNCTION ] = function ($ ch , $ fd , $ length ) use ($ body ) {
279
+ $ curlOptions [CURLOPT_READFUNCTION ] = function ($ ch , $ fd , $ length ) use ($ body ) {
310
280
return $ body ->read ($ length );
311
281
};
312
282
} else {
313
283
// Small body can be loaded into memory
314
- $ options [CURLOPT_POSTFIELDS ] = (string ) $ body ;
284
+ $ curlOptions [CURLOPT_POSTFIELDS ] = (string ) $ body ;
315
285
}
316
286
}
317
287
}
318
288
319
289
if ($ request ->getMethod () === 'HEAD ' ) {
320
290
// This will set HTTP method to "HEAD".
321
- $ options [CURLOPT_NOBODY ] = true ;
291
+ $ curlOptions [CURLOPT_NOBODY ] = true ;
322
292
} elseif ($ request ->getMethod () !== 'GET ' ) {
323
293
// GET is a default method. Other methods should be specified explicitly.
324
- $ options [CURLOPT_CUSTOMREQUEST ] = $ request ->getMethod ();
294
+ $ curlOptions [CURLOPT_CUSTOMREQUEST ] = $ request ->getMethod ();
325
295
}
326
296
327
- return $ options ;
297
+ return $ curlOptions ;
328
298
}
329
299
330
300
/**
331
301
* Create headers array for CURLOPT_HTTPHEADER.
332
302
*
333
- * @param RequestInterface $request
334
- * @param array $options cURL options
335
- *
336
303
* @return string[]
337
304
*/
338
- private function createHeaders (RequestInterface $ request , array $ options ): array
305
+ private function createHeaders (RequestInterface $ request , array $ curlOptions ): array
339
306
{
340
307
$ curlHeaders = [];
341
308
$ headers = $ request ->getHeaders ();
@@ -346,10 +313,10 @@ private function createHeaders(RequestInterface $request, array $options): array
346
313
continue ;
347
314
}
348
315
if ('content-length ' === $ header ) {
349
- if (array_key_exists (CURLOPT_POSTFIELDS , $ options )) {
316
+ if (array_key_exists (CURLOPT_POSTFIELDS , $ curlOptions )) {
350
317
// Small body content length can be calculated here.
351
- $ values = [strlen ($ options [CURLOPT_POSTFIELDS ])];
352
- } elseif (!array_key_exists (CURLOPT_READFUNCTION , $ options )) {
318
+ $ values = [strlen ($ curlOptions [CURLOPT_POSTFIELDS ])];
319
+ } elseif (!array_key_exists (CURLOPT_READFUNCTION , $ curlOptions )) {
353
320
// Else if there is no body, forcing "Content-length" to 0
354
321
$ values = [0 ];
355
322
}
@@ -367,11 +334,6 @@ private function createHeaders(RequestInterface $request, array $options): array
367
334
return $ curlHeaders ;
368
335
}
369
336
370
- /**
371
- * Create new ResponseBuilder instance.
372
- *
373
- * @return ResponseBuilder
374
- */
375
337
private function createResponseBuilder (): ResponseBuilder
376
338
{
377
339
$ body = $ this ->streamFactory ->createStreamFromFile ('php://temp ' , 'w+b ' );
0 commit comments