@@ -32,11 +32,18 @@ class Client implements HttpClient, HttpAsyncClient
32
32
private $ options ;
33
33
34
34
/**
35
- * cURL response parser
35
+ * PSR-7 message factory
36
36
*
37
- * @var ResponseParser
37
+ * @var MessageFactory
38
38
*/
39
- private $ responseParser ;
39
+ private $ messageFactory ;
40
+
41
+ /**
42
+ * PSR-7 stream factory
43
+ *
44
+ * @var StreamFactory
45
+ */
46
+ private $ streamFactory ;
40
47
41
48
/**
42
49
* cURL synchronous requests handle
@@ -66,7 +73,8 @@ public function __construct(
66
73
StreamFactory $ streamFactory ,
67
74
array $ options = []
68
75
) {
69
- $ this ->responseParser = new ResponseParser ($ messageFactory , $ streamFactory );
76
+ $ this ->messageFactory = $ messageFactory ;
77
+ $ this ->streamFactory = $ streamFactory ;
70
78
$ this ->options = $ options ;
71
79
}
72
80
@@ -87,15 +95,16 @@ public function __destruct()
87
95
*
88
96
* @return ResponseInterface
89
97
*
90
- * @throws RequestException
98
+ * @throws \RuntimeException If creating the body stream fails.
91
99
* @throws \UnexpectedValueException if unsupported HTTP version requested
92
- * @throws \RuntimeException if can not read body
100
+ * @throws RequestException
93
101
*
94
102
* @since 1.0
95
103
*/
96
104
public function sendRequest (RequestInterface $ request )
97
105
{
98
- $ options = $ this ->createCurlOptions ($ request );
106
+ $ responseBuilder = $ this ->createResponseBuilder ();
107
+ $ options = $ this ->createCurlOptions ($ request , $ responseBuilder );
99
108
100
109
if (is_resource ($ this ->handle )) {
101
110
curl_reset ($ this ->handle );
@@ -104,19 +113,14 @@ public function sendRequest(RequestInterface $request)
104
113
}
105
114
106
115
curl_setopt_array ($ this ->handle , $ options );
107
- $ raw = curl_exec ($ this ->handle );
116
+ curl_exec ($ this ->handle );
108
117
109
118
if (curl_errno ($ this ->handle ) > 0 ) {
110
119
throw new RequestException (curl_error ($ this ->handle ), $ request );
111
120
}
112
121
113
- $ info = curl_getinfo ($ this ->handle );
114
-
115
- try {
116
- $ response = $ this ->responseParser ->parse ($ raw , $ info );
117
- } catch (\Exception $ e ) {
118
- throw new RequestException ($ e ->getMessage (), $ request , $ e );
119
- }
122
+ $ response = $ responseBuilder ->getResponse ();
123
+ $ response ->getBody ()->seek (0 );
120
124
121
125
return $ response ;
122
126
}
@@ -128,23 +132,24 @@ public function sendRequest(RequestInterface $request)
128
132
*
129
133
* @return Promise
130
134
*
135
+ * @throws \RuntimeException If creating the body stream fails.
136
+ * @throws \UnexpectedValueException If unsupported HTTP version requested
131
137
* @throws Exception
132
- * @throws \UnexpectedValueException if unsupported HTTP version requested
133
- * @throws \RuntimeException if can not read body
134
138
*
135
139
* @since 1.0
136
140
*/
137
141
public function sendAsyncRequest (RequestInterface $ request )
138
142
{
139
143
if (!$ this ->multiRunner instanceof MultiRunner) {
140
- $ this ->multiRunner = new MultiRunner ($ this -> responseParser );
144
+ $ this ->multiRunner = new MultiRunner ();
141
145
}
142
146
143
147
$ handle = curl_init ();
144
- $ options = $ this ->createCurlOptions ($ request );
148
+ $ responseBuilder = $ this ->createResponseBuilder ();
149
+ $ options = $ this ->createCurlOptions ($ request , $ responseBuilder );
145
150
curl_setopt_array ($ handle , $ options );
146
151
147
- $ core = new PromiseCore ($ request , $ handle );
152
+ $ core = new PromiseCore ($ request , $ handle, $ responseBuilder );
148
153
$ promise = new CurlPromise ($ core , $ this ->multiRunner );
149
154
$ this ->multiRunner ->add ($ core );
150
155
@@ -155,18 +160,19 @@ public function sendAsyncRequest(RequestInterface $request)
155
160
* Generates cURL options
156
161
*
157
162
* @param RequestInterface $request
163
+ * @param ResponseBuilder $responseBuilder
158
164
*
159
165
* @throws \UnexpectedValueException if unsupported HTTP version requested
160
166
* @throws \RuntimeException if can not read body
161
167
*
162
168
* @return array
163
169
*/
164
- private function createCurlOptions (RequestInterface $ request )
170
+ private function createCurlOptions (RequestInterface $ request, ResponseBuilder $ responseBuilder )
165
171
{
166
172
$ options = $ this ->options ;
167
173
168
- $ options [CURLOPT_HEADER ] = true ;
169
- $ options [CURLOPT_RETURNTRANSFER ] = true ;
174
+ $ options [CURLOPT_HEADER ] = false ;
175
+ $ options [CURLOPT_RETURNTRANSFER ] = false ;
170
176
$ options [CURLOPT_FOLLOWLOCATION ] = false ;
171
177
172
178
$ options [CURLOPT_HTTP_VERSION ] = $ this ->getProtocolVersion ($ request ->getProtocolVersion ());
@@ -207,6 +213,23 @@ private function createCurlOptions(RequestInterface $request)
207
213
$ options [CURLOPT_USERPWD ] = $ request ->getUri ()->getUserInfo ();
208
214
}
209
215
216
+ $ options [CURLOPT_HEADERFUNCTION ] = function ($ ch , $ data ) use ($ responseBuilder ) {
217
+ $ str = trim ($ data );
218
+ if ('' !== $ str ) {
219
+ if (strpos (strtolower ($ str ), 'http/ ' ) === 0 ) {
220
+ $ responseBuilder ->setStatus ($ str )->getResponse ();
221
+ } else {
222
+ $ responseBuilder ->addHeader ($ str );
223
+ }
224
+ }
225
+
226
+ return strlen ($ data );
227
+ };
228
+
229
+ $ options [CURLOPT_WRITEFUNCTION ] = function ($ ch , $ data ) use ($ responseBuilder ) {
230
+ return $ responseBuilder ->getResponse ()->getBody ()->write ($ data );
231
+ };
232
+
210
233
return $ options ;
211
234
}
212
235
@@ -274,4 +297,23 @@ private function createHeaders(RequestInterface $request, array $options)
274
297
275
298
return $ curlHeaders ;
276
299
}
300
+
301
+ /**
302
+ * Create new ResponseBuilder instance
303
+ *
304
+ * @return ResponseBuilder
305
+ *
306
+ * @throws \RuntimeException If creating the stream from $body fails.
307
+ */
308
+ private function createResponseBuilder ()
309
+ {
310
+ try {
311
+ $ body = $ this ->streamFactory ->createStream (fopen ('php://temp ' , 'w+ ' ));
312
+ } catch (\InvalidArgumentException $ e ) {
313
+ throw new \RuntimeException ('Can not create "php://temp" stream. ' );
314
+ }
315
+ $ response = $ this ->messageFactory ->createResponse (200 , null , [], $ body );
316
+
317
+ return new ResponseBuilder ($ response );
318
+ }
277
319
}
0 commit comments