/** * @param string $method * @param string $url * @param array $payload * @param array $curlOptions * * @throws \InvalidArgumentException * @return bool|mixed|\stdClass */ protected static function _httpRequest($method = self::Get, $url, $payload = array(), $curlOptions = array()) { if (!static::contains($method)) { throw new \InvalidArgumentException('Invalid method "' . $method . '" specified.'); } // Reset! static::$_lastResponseHeaders = static::$_lastHttpCode = static::$_error = static::$_info = $_tmpFile = null; // Build a curl request... $_curl = curl_init($url); // Default CURL options for this method $_curlOptions = array(CURLOPT_FOLLOWLOCATION => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true, CURLINFO_HEADER_OUT => true, CURLOPT_SSL_VERIFYPEER => false); // Merge in the global options if any if (!empty(static::$_curlOptions)) { $curlOptions = array_merge($curlOptions, static::$_curlOptions); } // Add/override user options if (!empty($curlOptions)) { foreach ($curlOptions as $_key => $_value) { $_curlOptions[$_key] = $_value; } } if (null !== static::$_userName || null !== static::$_password) { $_curlOptions[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC; $_curlOptions[CURLOPT_USERPWD] = static::$_userName . ':' . static::$_password; } switch ($method) { case static::Get: // Do nothing, like the goggles... break; case static::Put: $_payload = json_encode(!empty($payload) ? $payload : array()); $_tmpFile = tmpfile(); fwrite($_tmpFile, $_payload); rewind($_tmpFile); $_curlOptions[CURLOPT_PUT] = true; $_curlOptions[CURLOPT_INFILE] = $_tmpFile; $_curlOptions[CURLOPT_INFILESIZE] = mb_strlen($_payload); break; case static::Post: $_curlOptions[CURLOPT_POST] = true; $_curlOptions[CURLOPT_POSTFIELDS] = $payload; break; case static::Head: $_curlOptions[CURLOPT_NOBODY] = true; break; case static::Patch: $_curlOptions[CURLOPT_CUSTOMREQUEST] = static::Patch; $_curlOptions[CURLOPT_POSTFIELDS] = $payload; break; case static::Merge: case static::Delete: /** Merge && Delete have payloads, but they and Options/Copy need CURLOPT_CUSTOMREQUEST set so just fall through... */ $_curlOptions[CURLOPT_POSTFIELDS] = $payload; case static::Options: case static::Copy: $_curlOptions[CURLOPT_CUSTOMREQUEST] = $method; break; } if (null !== static::$_hostPort && !isset($_curlOptions[CURLOPT_PORT])) { $_curlOptions[CURLOPT_PORT] = static::$_hostPort; } // Set our collected options curl_setopt_array($_curl, $_curlOptions); // Make the call! $_result = curl_exec($_curl); static::$_info = curl_getinfo($_curl); static::$_lastHttpCode = Option::get(static::$_info, 'http_code'); static::$_responseHeaders = curl_getinfo($_curl, CURLINFO_HEADER_OUT); static::$_responseHeadersSize = curl_getinfo($_curl, CURLINFO_HEADER_SIZE); if (static::$_debug) { // @todo Add debug output } if (false === $_result) { static::$_error = array('code' => curl_errno($_curl), 'message' => curl_error($_curl)); } elseif (true === $_result) { // Worked, but no data... $_result = null; } else { // Split up the body and headers if requested if ($_curlOptions[CURLOPT_HEADER]) { if (false === strpos($_result, "\r\n\r\n") || empty(static::$_responseHeadersSize)) { $_headers = $_result; $_body = null; } else { $_headers = substr($_result, 0, static::$_responseHeadersSize); $_body = substr($_result, static::$_responseHeadersSize); } if ($_headers) { static::$_lastResponseHeaders = array(); $_raw = explode("\r\n", $_headers); if (!empty($_raw)) { $_first = true; foreach ($_raw as $_line) { // Skip the first line (HTTP/1.x response) if ($_first || preg_match('/^HTTP\\/[0-9\\.]+ [0-9]+/', $_line)) { $_first = false; continue; } $_parts = explode(':', $_line, 2); if (!empty($_parts)) { static::$_lastResponseHeaders[trim($_parts[0])] = count($_parts) > 1 ? trim($_parts[1]) : null; } } } } $_result = $_body; } // Attempt to auto-decode inbound JSON if (!empty($_result) && false !== stripos(Option::get(static::$_info, 'content_type'), 'application/json', 0)) { try { if (false !== ($_json = @json_decode($_result, static::$_decodeToArray))) { $_result = $_json; } } catch (\Exception $_ex) { // Ignored Log::debug('Exception decoding result: ' . $_ex->getMessage()); } } // Don't confuse error with empty data... if (false === $_result) { $_result = null; } } @curl_close($_curl); // Close temp file if any if (null !== $_tmpFile) { @fclose($_tmpFile); } return $_result; }
/** * @param string $method * @param string $url * @param array $payload * @param array $curlOptions * * @throws \InvalidArgumentException * @return bool|mixed|\stdClass */ protected static function _httpRequest($method = self::GET, $url, $payload = [], $curlOptions = []) { if (!static::contains($method)) { throw new \InvalidArgumentException('Invalid method "' . $method . '" specified.'); } // Reset! static::$_lastResponseHeaders = static::$_lastHttpCode = static::$_error = static::$_info = $_tmpFile = null; // Build a curl request... $_curl = curl_init($url); // Default CURL options for this method $_curlOptions = [CURLOPT_FOLLOWLOCATION => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true, CURLINFO_HEADER_OUT => true, CURLOPT_SSL_VERIFYPEER => false]; // Merge in the global options if any if (!empty(static::$_curlOptions)) { $curlOptions = array_merge($curlOptions, static::$_curlOptions); } // Add/override user options if (!empty($curlOptions)) { foreach ($curlOptions as $_key => $_value) { $_curlOptions[$_key] = $_value; } } if (null !== static::$_userName || null !== static::$_password) { $_curlOptions[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC; $_curlOptions[CURLOPT_USERPWD] = static::$_userName . ':' . static::$_password; } // Set verb-specific CURL options switch ($method) { case static::PUT: if (static::$putAsFile) { $payload = json_encode(!empty($payload) ? $payload : []); $_tmpFile = tmpfile(); fwrite($_tmpFile, $payload); rewind($_tmpFile); $_curlOptions[CURLOPT_PUT] = true; $_curlOptions[CURLOPT_INFILE] = $_tmpFile; $_curlOptions[CURLOPT_INFILESIZE] = mb_strlen($payload); } else { $_curlOptions[CURLOPT_CUSTOMREQUEST] = static::PUT; $_curlOptions[CURLOPT_POSTFIELDS] = $payload; } break; case static::POST: $_curlOptions[CURLOPT_POST] = true; $_curlOptions[CURLOPT_POSTFIELDS] = $payload; break; case static::HEAD: $_curlOptions[CURLOPT_NOBODY] = true; break; /** Patch, Merge, and Delete have payloads */ /** Patch, Merge, and Delete have payloads */ case static::PATCH: case static::MERGE: case static::DELETE: $_curlOptions[CURLOPT_POSTFIELDS] = $payload; break; } // Non-standard verbs need custom request option set... if (!in_array($method, [static::GET, static::POST, static::HEAD, static::PUT])) { $_curlOptions[CURLOPT_CUSTOMREQUEST] = $method; } if (null !== static::$_hostPort && !isset($_curlOptions[CURLOPT_PORT])) { $_curlOptions[CURLOPT_PORT] = static::$_hostPort; } // Set our collected options curl_setopt_array($_curl, $_curlOptions); // Make the call! $_result = curl_exec($_curl); static::$_info = curl_getinfo($_curl); static::$_lastHttpCode = ArrayUtils::get(static::$_info, 'http_code'); static::$_responseHeaders = curl_getinfo($_curl, CURLINFO_HEADER_OUT); static::$_responseHeadersSize = curl_getinfo($_curl, CURLINFO_HEADER_SIZE); if (false === $_result) { static::$_error = ['code' => curl_errno($_curl), 'message' => curl_error($_curl)]; } elseif (true === $_result) { // Worked, but no data... $_result = null; } else { // Split up the body and headers if requested if ($_curlOptions[CURLOPT_HEADER]) { if (false === strpos($_result, "\r\n\r\n") || empty(static::$_responseHeadersSize)) { $_headers = $_result; $_body = null; } else { $_headers = substr($_result, 0, static::$_responseHeadersSize); $_body = substr($_result, static::$_responseHeadersSize); } if ($_headers) { static::$_lastResponseHeaders = []; $_raw = explode("\r\n", $_headers); if (!empty($_raw)) { $_first = true; foreach ($_raw as $_line) { // Skip the first line (HTTP/1.x response) if ($_first || preg_match('/^HTTP\\/[0-9\\.]+ [0-9]+/', $_line)) { $_first = false; continue; } $_parts = explode(':', $_line, 2); if (!empty($_parts)) { static::$_lastResponseHeaders[trim($_parts[0])] = count($_parts) > 1 ? trim($_parts[1]) : null; } } } } $_result = $_body; } // Attempt to auto-decode inbound JSON if (!empty($_result) && false !== stripos(ArrayUtils::get(static::$_info, 'content_type'), 'application/json', 0)) { try { if (false !== ($_json = @json_decode($_result, static::$_decodeToArray))) { $_result = $_json; } } catch (\Exception $_ex) { // Ignored } } // Don't confuse error with empty data... if (false === $_result) { $_result = null; } } @curl_close($_curl); // Close temp file if any if (null !== $_tmpFile) { @fclose($_tmpFile); } return $_result; }