public function request(Request $request)
 {
     $context = stream_context_create(array('http' => array('method' => $request->getRequestMethod(), 'header' => $request->getHeadersAsString(), 'proxy' => $request->getProxy(), 'content' => $request->getContentBody(), 'request_fulluri' => $request->hasProxy(), 'ignore_errors' => true)));
     /* Note: stream_socket_client does not support http(s) protocol. we have to use fopen here. */
     $socket = fopen($request->getUrl(), 'r', false, $context);
     if (!is_resource($socket)) {
         throw new \Exception("can't create stream socket.");
     }
     $headers = array();
     $meta_data = stream_get_meta_data($socket);
     if (isset($meta_data['wrapper_data'])) {
         foreach ($meta_data['wrapper_data'] as $value) {
             if (strpos($value, "HTTP/") === 0) {
                 list($dummy, $status, $dummy) = explode(" ", $value, 3);
                 $headers['HTTP_CODE'] = $status;
             } else {
                 list($key, $value) = explode(":", $value, 2);
                 $headers[$key] = $value;
             }
         }
     }
     if ($headers['HTTP_CODE'][0] != 2) {
         throw new \Exception(sprintf("API Server returns %s code: %s", $headers['HTTP_STATUS'], fread($socket, 8192)));
     }
     $data = stream_get_contents($socket);
     fclose($socket);
     return array($headers, $data);
 }
 protected function requestImpl($http_method = "GET", $endpoint, $query, $params, $post_field = array(), Request $request)
 {
     //$curl = curl_copy_handle($this->curl);
     $curl = $this->curl;
     $url = $endpoint . $query;
     if (!empty($params)) {
         $url .= "?" . http_build_query($params);
     }
     curl_setopt($curl, CURLOPT_URL, $url);
     //curl_setopt($curl, CURLINFO_HEADER_OUT, true);
     $headers = array();
     foreach ($request->getHeaders() as $key => $value) {
         if ($key == "Content-Length") {
             /* Note: curl don't need content length as calculate itself */
             continue;
         }
         $headers[] = sprintf("%s: %s", $key, $value);
     }
     curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
     if ($http_method == "POST") {
         curl_setopt($curl, CURLOPT_POST, 1);
         curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getContentBody());
     } else {
         if ($http_method == "GET") {
             curl_setopt($curl, CURLOPT_HTTPGET, 1);
         } else {
             if ($http_method == 'PUT') {
                 curl_setopt($curl, CURLOPT_PUT, 1);
                 curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getContentBody());
             } else {
                 if ($http_method == 'DELETE') {
                     curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
                     curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getContentBody());
                 } else {
                     throw new \Exception("unsupported httpd method: " . $http_method);
                 }
             }
         }
     }
     $response = curl_exec($curl);
     $info = curl_getinfo($curl);
     $header = substr($response, 0, $info['header_size']);
     $headers = array();
     foreach (preg_split("/\r?\n/", trim($header)) as $line) {
         if (!isset($headers['HTTP_CODE'])) {
             list($version, $status, $status) = explode(" ", $line, 3);
             $headers['HTTP_CODE'] = $status;
         } else {
             @(list($key, $value) = explode(":", $line, 2));
             $headers[$key] = trim($value);
         }
     }
     $output = substr($response, $info['header_size']);
     return array($headers, $output);
 }