@@ -32,11 +32,18 @@ class Client implements HttpClient, HttpAsyncClient
3232 private $ options ;
3333
3434 /**
35- * cURL response parser
35+ * PSR-7 message factory
3636 *
37- * @var ResponseParser
37+ * @var MessageFactory
3838 */
39- private $ responseParser ;
39+ private $ messageFactory ;
40+
41+ /**
42+ * PSR-7 stream factory
43+ *
44+ * @var StreamFactory
45+ */
46+ private $ streamFactory ;
4047
4148 /**
4249 * cURL synchronous requests handle
@@ -66,7 +73,8 @@ public function __construct(
6673 StreamFactory $ streamFactory ,
6774 array $ options = []
6875 ) {
69- $ this ->responseParser = new ResponseParser ($ messageFactory , $ streamFactory );
76+ $ this ->messageFactory = $ messageFactory ;
77+ $ this ->streamFactory = $ streamFactory ;
7078 $ this ->options = $ options ;
7179 }
7280
@@ -87,15 +95,16 @@ public function __destruct()
8795 *
8896 * @return ResponseInterface
8997 *
90- * @throws RequestException
98+ * @throws \RuntimeException If creating the body stream fails.
9199 * @throws \UnexpectedValueException if unsupported HTTP version requested
92- * @throws \RuntimeException if can not read body
100+ * @throws RequestException
93101 *
94102 * @since 1.0
95103 */
96104 public function sendRequest (RequestInterface $ request )
97105 {
98- $ options = $ this ->createCurlOptions ($ request );
106+ $ responseBuilder = $ this ->createResponseBuilder ();
107+ $ options = $ this ->createCurlOptions ($ request , $ responseBuilder );
99108
100109 if (is_resource ($ this ->handle )) {
101110 curl_reset ($ this ->handle );
@@ -104,19 +113,14 @@ public function sendRequest(RequestInterface $request)
104113 }
105114
106115 curl_setopt_array ($ this ->handle , $ options );
107- $ raw = curl_exec ($ this ->handle );
116+ curl_exec ($ this ->handle );
108117
109118 if (curl_errno ($ this ->handle ) > 0 ) {
110119 throw new RequestException (curl_error ($ this ->handle ), $ request );
111120 }
112121
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 );
120124
121125 return $ response ;
122126 }
@@ -128,23 +132,24 @@ public function sendRequest(RequestInterface $request)
128132 *
129133 * @return Promise
130134 *
135+ * @throws \RuntimeException If creating the body stream fails.
136+ * @throws \UnexpectedValueException If unsupported HTTP version requested
131137 * @throws Exception
132- * @throws \UnexpectedValueException if unsupported HTTP version requested
133- * @throws \RuntimeException if can not read body
134138 *
135139 * @since 1.0
136140 */
137141 public function sendAsyncRequest (RequestInterface $ request )
138142 {
139143 if (!$ this ->multiRunner instanceof MultiRunner) {
140- $ this ->multiRunner = new MultiRunner ($ this -> responseParser );
144+ $ this ->multiRunner = new MultiRunner ();
141145 }
142146
143147 $ handle = curl_init ();
144- $ options = $ this ->createCurlOptions ($ request );
148+ $ responseBuilder = $ this ->createResponseBuilder ();
149+ $ options = $ this ->createCurlOptions ($ request , $ responseBuilder );
145150 curl_setopt_array ($ handle , $ options );
146151
147- $ core = new PromiseCore ($ request , $ handle );
152+ $ core = new PromiseCore ($ request , $ handle, $ responseBuilder );
148153 $ promise = new CurlPromise ($ core , $ this ->multiRunner );
149154 $ this ->multiRunner ->add ($ core );
150155
@@ -155,18 +160,19 @@ public function sendAsyncRequest(RequestInterface $request)
155160 * Generates cURL options
156161 *
157162 * @param RequestInterface $request
163+ * @param ResponseBuilder $responseBuilder
158164 *
159165 * @throws \UnexpectedValueException if unsupported HTTP version requested
160166 * @throws \RuntimeException if can not read body
161167 *
162168 * @return array
163169 */
164- private function createCurlOptions (RequestInterface $ request )
170+ private function createCurlOptions (RequestInterface $ request, ResponseBuilder $ responseBuilder )
165171 {
166172 $ options = $ this ->options ;
167173
168- $ options [CURLOPT_HEADER ] = true ;
169- $ options [CURLOPT_RETURNTRANSFER ] = true ;
174+ $ options [CURLOPT_HEADER ] = false ;
175+ $ options [CURLOPT_RETURNTRANSFER ] = false ;
170176 $ options [CURLOPT_FOLLOWLOCATION ] = false ;
171177
172178 $ options [CURLOPT_HTTP_VERSION ] = $ this ->getProtocolVersion ($ request ->getProtocolVersion ());
@@ -207,6 +213,23 @@ private function createCurlOptions(RequestInterface $request)
207213 $ options [CURLOPT_USERPWD ] = $ request ->getUri ()->getUserInfo ();
208214 }
209215
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+
210233 return $ options ;
211234 }
212235
@@ -274,4 +297,23 @@ private function createHeaders(RequestInterface $request, array $options)
274297
275298 return $ curlHeaders ;
276299 }
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+ }
277319}
0 commit comments