diff --git a/src/CurlWrapper.php b/src/CurlWrapper.php index 3a0f636..01e7969 100644 --- a/src/CurlWrapper.php +++ b/src/CurlWrapper.php @@ -7,8 +7,29 @@ class CurlWrapper const USER_AGENT = 'gonzalo123/rest-proxy'; private $responseHeaders = []; + private $responseHeaderSize; + private $requestHeaders = []; + private $options = []; private $status; + /** + * @param array $requestHeaders Additional Curl Request headers + * @param array $options Array of key value pairs for additional Curl options (e.g. CURLOPT_SSL_VERIFYHOST => 0) + */ + function __construct($requestHeaders = array(), $options = array()) + { + if ( count($requestHeaders) > 0 && is_array($requestHeaders) ) { + $this->requestHeaders = $requestHeaders; + $this->requestHeaders[] = "User-Agent: " . self::USER_AGENT; + } else { + $this->requestHeaders = ["User-Agent: " . self::USER_AGENT]; + } + if ( count($options) > 0 && is_array($options) ) { + $this->options = $options; + } + } + + public function doGet($url, $queryString = NULL) { $s = curl_init(); @@ -41,6 +62,18 @@ public function doPut($url, $queryString = NULL) return $this->doMethod($s); } + public function doOptions($url, $queryString = NULL) + { + $s = curl_init(); + curl_setopt($s, CURLOPT_URL, $url); + curl_setopt($s, CURLOPT_CUSTOMREQUEST, 'OPTIONS'); + if (!is_null($queryString)) { + curl_setopt($s, CURLOPT_POSTFIELDS, parse_str($queryString)); + } + + return $this->doMethod($s); + } + public function doDelete($url, $queryString = NULL) { $s = curl_init(); @@ -55,16 +88,22 @@ public function doDelete($url, $queryString = NULL) private function doMethod($s) { - $headers = ["User-Agent: " . self::USER_AGENT]; - curl_setopt($s, CURLOPT_HTTPHEADER, $headers); + curl_setopt($s, CURLOPT_HTTPHEADER, $this->requestHeaders); curl_setopt($s, CURLOPT_HEADER, TRUE); + curl_setopt($s, CURLINFO_HEADER_OUT, FALSE); curl_setopt($s, CURLOPT_RETURNTRANSFER, TRUE); - $out = curl_exec($s); - $this->status = curl_getinfo($s, CURLINFO_HTTP_CODE); - $this->responseHeaders = curl_getinfo($s, CURLINFO_HEADER_OUT); + foreach ($this->options as $option => $value) + { + curl_setopt($s, $option, $value); + } + $out = curl_exec($s); + $this->status = curl_getinfo($s, CURLINFO_HTTP_CODE); + $this->responseHeaders = curl_getinfo($s, CURLINFO_HEADER_OUT); + $this->responseHeaderSize = curl_getinfo($s, CURLINFO_HEADER_SIZE); curl_close($s); list($this->responseHeaders, $content) = $this->decodeOut($out); + if ($this->status != self::HTTP_OK) { throw new \Exception("http error: {$this->status}", $this->status); } @@ -74,25 +113,18 @@ private function doMethod($s) private function decodeOut($out) { - // It should be a fancy way to do that :( - $headersFinished = FALSE; - $headers = $content = []; - $data = explode("\n", $out); - foreach ($data as $line) { - if (trim($line) == '') { - $headersFinished = TRUE; - } else { - if ($headersFinished === FALSE && strpos($line, ':') > 0) { - $headers[] = $line; - } - - if ($headersFinished) { - $content[] = $line; - } + // Split content and headers via header-size parameter + $headerString = substr($out, 0, $this->responseHeaderSize); + $content = trim(substr($out, $this->responseHeaderSize)); + $headers = array(); + foreach (explode("\n", $headerString) as $key => $value) + { + if (trim($value) !== '') { + $headers[] = trim($value); } } - return [$headers, implode("\n", $content)]; + return [$headers, $content]; } public function getStatus() @@ -104,4 +136,4 @@ public function getHeaders() { return $this->responseHeaders; } -} \ No newline at end of file +}