diff --git a/changelog.txt b/changelog.txt index bd0582adf9871f41f340f8b26cc83848ee376bef..a6b253c9422e059658ac960150c33121ad6bbce6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ += 1.0.2 - 2019-12-06 = +* Fixed issue with headers + = 1.0.1 - 2019-12-05 = * Fixed issue with slicing resposne on CurlClient diff --git a/src/Curl/CurlClient.php b/src/Curl/CurlClient.php index 9d992e82b4796003aa3cd360aaf9fbcfd18bf6e3..17939aa859c0bd468279d495cc81fc595b37e2b1 100644 --- a/src/Curl/CurlClient.php +++ b/src/Curl/CurlClient.php @@ -1,206 +1,202 @@ <?php -namespace WPDesk\HttpClient\Curl; - -use WPDesk\HttpClient\HttpClient; -use WPDesk\HttpClient\HttpClientResponse; -use WPDesk\HttpClient\HttpClientRequestException; - -class CurlClient implements HttpClient -{ - /** @var resource */ - private $curlResource; - - /** @var string|null|boolean */ - private $rawResponse; - - /** @var int */ - private $httpResponseCode; - - /** - * @param string $url - * @param string $body - * @param array $headers - * @param int $timeOut - * @return HttpClientResponse - * @throws HttpClientRequestException - */ - public function get($url, $body, array $headers, $timeOut) - { - return $this->send($url, 'GET', $body, $headers, $timeOut); - } - - /** - * @param string $url - * @param string $method - * @param string $body - * @param array $headers - * @param int $timeOut - * @return HttpClientResponse - * @throws HttpClientRequestException - */ - public function send($url, $method, $body, array $headers, $timeOut) - { - $this->initResource(); - try { - $this->prepareConnection($url, $method, $body, $headers, $timeOut); - $this->sendRequest(); - $this->throwExceptionIfError(); - $this->closeConnection(); - - return $this->prepareResponse(); - - } catch (\Exception $e) { - $this->closeConnection(); - if ($e instanceof HttpClientRequestException) { - throw $e; - } - throw CurlExceptionFactory::createDefaultException($e->getMessage(), $e->getCode(), $e); - } - } - - private function initResource() - { - $this->curlResource = curl_init(); - } - - /** - * Opens a new curl connection. - * - * @param string $url The endpoint to send the request to. - * @param string $method The request method. - * @param string $body The body of the request. - * @param array $headers The request headers. - * @param int $timeOut The timeout in seconds for the request. - */ - private function prepareConnection($url, $method, $body, array $headers, $timeOut) - { - $options = [ - CURLOPT_CUSTOMREQUEST => $method, - CURLOPT_HTTPHEADER => $this->compileRequestHeaders($headers), - CURLOPT_URL => $url, - CURLOPT_CONNECTTIMEOUT => 10, - CURLOPT_TIMEOUT => $timeOut, - CURLOPT_RETURNTRANSFER => true, // Return response as string - CURLOPT_HEADER => true, // Enable header processing - CURLOPT_SSL_VERIFYHOST => 2, - CURLOPT_SSL_VERIFYPEER => true, - //CURLOPT_CAINFO => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem', - ]; - if ($method !== "GET") { - $options[CURLOPT_POSTFIELDS] = $body; - } - - curl_setopt_array($this->curlResource, $options); - } - - /** - * Compiles the request headers into a curl-friendly format. - * - * @param array $headers The request headers. - * - * @return array - */ - private function compileRequestHeaders(array $headers) - { - $return = []; - foreach ($headers as $key => $value) { - $return[] = $key . ': ' . $value; - } - return $return; - } - - /** - * Send the request and get the raw response from curl - */ - private function sendRequest() - { - $this->rawResponse = curl_exec($this->curlResource); - $this->httpResponseCode = $this->getHttpResponseCode(); - } - - /** @return int */ - private function getHttpResponseCode() - { - return intval(curl_getinfo($this->curlResource, CURLINFO_HTTP_CODE)); - } - - private function throwExceptionIfError() - { - $errorNumber = curl_errno($this->curlResource); - if ($errorNumber === 0) { - return; - } - - $errorMessage = curl_error($this->curlResource); - throw CurlExceptionFactory::createCurlException($errorMessage, $errorNumber); - } - - /** - * Closes an existing curl connection - */ - private function closeConnection() - { - curl_close($this->curlResource); - $this->curlResource = null; - } - - private function prepareResponse() - { - list($rawHeaders, $rawBody) = $this->extractResponseHeadersAndBody(); - return new HttpClientResponse($rawHeaders, $rawBody, $this->httpResponseCode); - } - - /** - * Extracts the headers and the body into a two-part array - * - * @return array - */ - private function extractResponseHeadersAndBody() - { - $parts = explode("\r\n\r\n", $this->rawResponse, 2 ); - $rawBody = array_pop($parts); - $rawHeaders = implode("\r\n\r\n", $parts); - return [trim($rawHeaders), trim($rawBody)]; - } - - /** - * @param string $url - * @param string $body - * @param array $headers - * @param int $timeOut - * @return HttpClientResponse - * @throws HttpClientRequestException - */ - public function post($url, $body, array $headers, $timeOut) - { - return $this->send($url, 'POST', $body, $headers, $timeOut); - } - - /** - * @param string $url - * @param string $body - * @param array $headers - * @param int $timeOut - * @return HttpClientResponse - * @throws HttpClientRequestException - */ - public function delete($url, $body, array $headers, $timeOut) - { - return $this->send($url, 'DELETE', $body, $headers, $timeOut); - } - - /** - * @param string $url - * @param string $body - * @param array $headers - * @param int $timeOut - * @return HttpClientResponse - * @throws HttpClientRequestException - */ - public function put($url, $body, array $headers, $timeOut) - { - return $this->send($url, 'PUT', $body, $headers, $timeOut); - } - +namespace iFirmaVendor\WPDesk\HttpClient\Curl; + +use iFirmaVendor\WPDesk\HttpClient\HttpClient; +use iFirmaVendor\WPDesk\HttpClient\HttpClientResponse; +use iFirmaVendor\WPDesk\HttpClient\HttpClientRequestException; + +class CurlClient implements \iFirmaVendor\WPDesk\HttpClient\HttpClient { + /** @var resource */ + private $curlResource; + /** @var string|null|boolean */ + private $rawResponse; + /** @var int */ + private $httpResponseCode; + /** @var array */ + private $headers = array(); + + /** + * @param string $url + * @param string $body + * @param array $headers + * @param int $timeOut + * + * @return HttpClientResponse + * @throws HttpClientRequestException + */ + public function get( $url, $body, array $headers, $timeOut ) { + return $this->send( $url, 'GET', $body, $headers, $timeOut ); + } + + /** + * @param string $url + * @param string $method + * @param string $body + * @param array $headers + * @param int $timeOut + * + * @return HttpClientResponse + * @throws HttpClientRequestException + */ + public function send( $url, $method, $body, array $headers, $timeOut ) { + $this->initResource(); + try { + $this->prepareConnection( $url, $method, $body, $headers, $timeOut ); + $this->sendRequest(); + $this->throwExceptionIfError(); + $this->closeConnection(); + + return $this->prepareResponse(); + } catch ( \Exception $e ) { + $this->closeConnection(); + if ( $e instanceof \iFirmaVendor\WPDesk\HttpClient\HttpClientRequestException ) { + throw $e; + } + throw \iFirmaVendor\WPDesk\HttpClient\Curl\CurlExceptionFactory::createDefaultException( $e->getMessage(), $e->getCode(), $e ); + } + } + + private function initResource() { + $this->curlResource = \curl_init(); + } + + /** + * Opens a new curl connection. + * + * @param string $url The endpoint to send the request to. + * @param string $method The request method. + * @param string $body The body of the request. + * @param array $headers The request headers. + * @param int $timeOut The timeout in seconds for the request. + */ + private function prepareConnection( $url, $method, $body, array $headers, $timeOut ) { + + $options = [ + \CURLOPT_CUSTOMREQUEST => $method, + \CURLOPT_HTTPHEADER => $this->compileRequestHeaders( $headers ), + \CURLOPT_URL => $url, + \CURLOPT_CONNECTTIMEOUT => 10, + \CURLOPT_TIMEOUT => $timeOut, + \CURLOPT_RETURNTRANSFER => \true, + // Return response as string + \CURLOPT_HEADER => \false, + // Enable header processing + \CURLOPT_SSL_VERIFYHOST => 2, + \CURLOPT_SSL_VERIFYPEER => \true, + \CURLOPT_HEADERFUNCTION => function ( $curl, $header ) { + $len = strlen( $header ); + $this->headers[] = trim( $header ); + + return $len; + } + ]; + if ( $method !== "GET" ) { + $options[ \CURLOPT_POSTFIELDS ] = $body; + } + \curl_setopt_array( $this->curlResource, $options ); + } + + /** + * Compiles the request headers into a curl-friendly format. + * + * @param array $headers The request headers. + * + * @return array + */ + private function compileRequestHeaders( array $headers ) { + $return = []; + foreach ( $headers as $key => $value ) { + $return[] = $key . ': ' . $value; + } + + return $return; + } + + /** + * Send the request and get the raw response from curl + */ + private function sendRequest() { + $this->rawResponse = \curl_exec( $this->curlResource ); + $this->httpResponseCode = $this->getHttpResponseCode(); + } + + /** @return int */ + private function getHttpResponseCode() { + return \intval( \curl_getinfo( $this->curlResource, \CURLINFO_HTTP_CODE ) ); + } + + private function throwExceptionIfError() { + $errorNumber = \curl_errno( $this->curlResource ); + if ( $errorNumber === 0 ) { + return; + } + $errorMessage = \curl_error( $this->curlResource ); + throw \iFirmaVendor\WPDesk\HttpClient\Curl\CurlExceptionFactory::createCurlException( $errorMessage, $errorNumber ); + } + + /** + * Closes an existing curl connection + */ + private function closeConnection() { + \curl_close( $this->curlResource ); + $this->curlResource = null; + } + + private function prepareResponse() { + list( $rawHeaders, $rawBody ) = $this->extractResponseHeadersAndBody(); + + return new \iFirmaVendor\WPDesk\HttpClient\HttpClientResponse( $rawHeaders, $rawBody, $this->httpResponseCode ); + } + + /** + * Extracts the headers and the body into a two-part array + * + * @return array + */ + private function extractResponseHeadersAndBody() { + $rawBody = \trim( $this->rawResponse ); + $rawHeaders = \trim( implode( "\r\n", $this->headers ) ); + + return [ $rawHeaders, $rawBody ]; + } + + /** + * @param string $url + * @param string $body + * @param array $headers + * @param int $timeOut + * + * @return HttpClientResponse + * @throws HttpClientRequestException + */ + public function post( $url, $body, array $headers, $timeOut ) { + return $this->send( $url, 'POST', $body, $headers, $timeOut ); + } + + /** + * @param string $url + * @param string $body + * @param array $headers + * @param int $timeOut + * + * @return HttpClientResponse + * @throws HttpClientRequestException + */ + public function delete( $url, $body, array $headers, $timeOut ) { + return $this->send( $url, 'DELETE', $body, $headers, $timeOut ); + } + + /** + * @param string $url + * @param string $body + * @param array $headers + * @param int $timeOut + * + * @return HttpClientResponse + * @throws HttpClientRequestException + */ + public function put( $url, $body, array $headers, $timeOut ) { + return $this->send( $url, 'PUT', $body, $headers, $timeOut ); + } } \ No newline at end of file