1212use Psr \Http \Message \ResponseInterface ;
1313use Psr \Http \Message \StreamFactoryInterface ;
1414use Psr \Http \Message \UriInterface ;
15+ use SharkMachine \Psr18Shark \Exception \ClientException ;
1516use SharkMachine \Psr18Shark \Exception \CurlException ;
1617use SharkMachine \Psr18Shark \Exception \NoResponseException ;
1718use SharkMachine \Psr18Shark \Handler \RequestMutationHandlerCollection ;
@@ -28,16 +29,6 @@ class Client implements ClientInterface
2829 */
2930 private CurlHandle $ curl ;
3031
31- /**
32- * @var string
33- */
34- private string $ dataStream = '' ;
35-
36- /**
37- * @var array<string, string[]>
38- */
39- private array $ responseHeaders = [];
40-
4132 /**
4233 * @param ResponseFactoryInterface $responseFactory
4334 * @param StreamFactoryInterface $streamFactory
@@ -79,10 +70,10 @@ public function sendRequest(RequestInterface $request): ResponseInterface
7970 }
8071 }
8172
82- $ this ->initCurl ($ request ->getUri ());
8373 try {
84- $ this ->curlRequest ($ request );
85- $ response = $ this ->getResponse ();
74+ $ responseData = $ this ->initCurl ($ request ->getUri ());
75+ $ this ->curlRequest ($ request , $ responseData );
76+ $ response = $ this ->getResponse ($ responseData );
8677 } catch (Throwable $ ex ) {
8778 curl_close ($ this ->curl );
8879 if (null !== $ this ->transferHandlerCollection ) {
@@ -111,11 +102,18 @@ public function sendRequest(RequestInterface $request): ResponseInterface
111102 /**
112103 * @param UriInterface $uri
113104 *
114- * @return void
105+ * @return ResponseData
106+ *
107+ * @throws ClientException
115108 */
116- protected function initCurl (UriInterface $ uri ): void
109+ protected function initCurl (UriInterface $ uri ): ResponseData
117110 {
118111 $ this ->curl = curl_init ((string )$ uri );
112+ $ dataStream = fopen ('php://temp ' , 'wb+ ' );
113+ if (false === $ dataStream ) {
114+ throw new ClientException ('Unable to open handle for response ' );
115+ }
116+ $ responseData = new ResponseData ($ dataStream );
119117
120118 // Do not follow redirects.
121119 curl_setopt ($ this ->curl , CURLOPT_FOLLOWLOCATION , false );
@@ -124,28 +122,31 @@ protected function initCurl(UriInterface $uri): void
124122 curl_setopt (
125123 $ this ->curl ,
126124 CURLOPT_WRITEFUNCTION ,
127- function (CurlHandle $ curl , string $ data ): int {
128- $ this ->dataStream .= $ data ;
129- return strlen ($ data );
125+ static function (CurlHandle $ curl , string $ data ) use ($ responseData ): int {
126+ $ bytes = fwrite ($ responseData ->streamHandle , $ data );
127+ if (false === $ bytes ) {
128+ return -1 ; // This will cause a cURL error
129+ }
130+ return $ bytes ;
130131 }
131132 );
132133
133134 // Get headers
134135 curl_setopt (
135136 $ this ->curl ,
136137 CURLOPT_HEADERFUNCTION ,
137- function (CurlHandle $ curl , string $ header ): int {
138+ static function (CurlHandle $ curl , string $ header) use ( $ responseData ): int {
138139 $ len = strlen ($ header );
139140 $ headerArray = explode (': ' , $ header , 2 );
140141 if (count ($ headerArray ) < 2 ) {
141142 return $ len ;
142143 }
143144 $ headerName = strtolower (trim ($ headerArray [0 ]));
144145 if (!str_contains ($ headerArray [1 ], ', ' )) {
145- $ this -> responseHeaders [$ headerName ] = [trim ($ headerArray [1 ])];
146+ $ responseData -> headers [$ headerName ] = [trim ($ headerArray [1 ])];
146147 return $ len ;
147148 }
148- $ this -> responseHeaders [$ headerName ] = array_map (
149+ $ responseData -> headers [$ headerName ] = array_map (
149150 'trim ' ,
150151 explode (', ' , $ headerArray [1 ])
151152 );
@@ -175,20 +176,20 @@ function (CurlHandle $curl, string $header): int {
175176 if (!in_array (CURLOPT_USERAGENT , $ this ->curlOptions , true )) {
176177 curl_setopt ($ this ->curl , CURLOPT_USERAGENT , self ::DEFAULT_USER_AGENT );
177178 }
179+
180+ return $ responseData ;
178181 }
179182
180183 /**
181184 * @param RequestInterface $request
185+ * @param ResponseData $responseData
182186 *
183- * @return void
187+ * @return ResponseData
184188 *
185189 * @throws ClientExceptionInterface
186190 */
187- protected function curlRequest (RequestInterface $ request ): void
191+ protected function curlRequest (RequestInterface $ request, ResponseData $ responseData ): ResponseData
188192 {
189- $ this ->dataStream = '' ;
190- $ this ->responseHeaders = [];
191-
192193 if (count ($ request ->getHeaders ()) > 0 ) {
193194 $ headers = [];
194195 foreach ($ request ->getHeaders () as $ headerName => $ headerValues ) {
@@ -209,19 +210,23 @@ protected function curlRequest(RequestInterface $request): void
209210 if (false === curl_exec ($ this ->curl )) {
210211 throw new CurlException (curl_error ($ this ->curl ));
211212 }
213+ return $ responseData ;
212214 }
213215
214216 /**
217+ * @param ResponseData $responseData
218+ *
215219 * @return ResponseInterface
216220 */
217- protected function getResponse (): ResponseInterface
221+ protected function getResponse (ResponseData $ responseData ): ResponseInterface
218222 {
219223 $ statusCode = curl_getinfo ($ this ->curl , CURLINFO_HTTP_CODE );
220224 $ response = $ this ->responseFactory ->createResponse ($ statusCode );
221- $ response = $ response ->withBody ($ this ->streamFactory ->createStream ( $ this -> dataStream ));
222- foreach ($ this -> responseHeaders as $ headerName => $ headerValue ) {
225+ $ response = $ response ->withBody ($ this ->streamFactory ->createStreamFromResource ( $ responseData -> streamHandle ));
226+ foreach ($ responseData -> headers as $ headerName => $ headerValue ) {
223227 $ response = $ response ->withHeader ($ headerName , $ headerValue );
224228 }
229+ $ response ->getBody ()->rewind ();
225230 if (null !== $ this ->responseMutationHandlerCollection ) {
226231 foreach ($ this ->responseMutationHandlerCollection as $ handler ) {
227232 $ response = $ handler ->handleResponse ($ response );
0 commit comments