You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
6.4 KiB
PHTML
175 lines
6.4 KiB
PHTML
5 years ago
|
<?php
|
||
|
|
||
|
namespace qcloudcos;
|
||
|
|
||
|
class HttpRequest {
|
||
|
public $timeoutMs; // int: the maximum number of milliseconds to perform this request.
|
||
|
public $url; // string: the url this request will be sent to.
|
||
|
public $method; // string: POST or GET.
|
||
|
public $customHeaders; // array: custom modified, removed and added headers.
|
||
|
public $dataToPost; // array: the data to post.
|
||
|
public $userData; // any: user custom data.
|
||
|
}
|
||
|
|
||
|
class HttpResponse {
|
||
|
public $curlErrorCode; // int: curl last error code.
|
||
|
public $curlErrorMessage; // string: curl last error message.
|
||
|
public $statusCode; // int: http status code.
|
||
|
public $headers; // array: response headers.
|
||
|
public $body; // string: response body.
|
||
|
}
|
||
|
|
||
|
// A simple wrapper for libcurl using multi interface to do transfers in parallel.
|
||
|
class LibcurlWrapper {
|
||
|
private $sequence; // integer: sequence id for each request.
|
||
|
private $curlMultiHandle; // curl handle: curl multi handle.
|
||
|
private $curlHandleInfo; // array: array of active curl handle.
|
||
|
private $idleCurlHandle; // array: idle curl handle which can be reused.
|
||
|
|
||
|
public function __construct() {
|
||
|
$this->sequence = 0;
|
||
|
$this->curlMultiHandle = curl_multi_init();
|
||
|
$this->idleCurlHandle = array();
|
||
|
}
|
||
|
|
||
|
public function __destruct() {
|
||
|
curl_multi_close($this->curlMultiHandle);
|
||
|
foreach ($this->idleCurlHandle as $handle) {
|
||
|
curl_close($handle);
|
||
|
}
|
||
|
$this->idleCurlHandle = array();
|
||
|
}
|
||
|
|
||
|
public function startSendingRequest($httpRequest, $done) {
|
||
|
$this->sequence += 1;
|
||
|
|
||
|
if (count($this->idleCurlHandle) !== 0) {
|
||
|
$curlHandle = array_pop($this->idleCurlHandle);
|
||
|
} else {
|
||
|
$curlHandle = curl_init();
|
||
|
if ($curlHandle === false) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
curl_setopt($curlHandle, CURLOPT_TIMEOUT_MS, $httpRequest->timeoutMs);
|
||
|
curl_setopt($curlHandle, CURLOPT_URL, $httpRequest->url);
|
||
|
curl_setopt($curlHandle, CURLOPT_HEADER, 1);
|
||
|
curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);
|
||
|
$headers = $httpRequest->customHeaders;
|
||
|
array_push($headers, 'User-Agent:'.Conf::getUserAgent());
|
||
|
if ($httpRequest->method === 'POST') {
|
||
|
if (defined('CURLOPT_SAFE_UPLOAD')) {
|
||
|
curl_setopt($curlHandle, CURLOPT_SAFE_UPLOAD, true);
|
||
|
}
|
||
|
|
||
|
curl_setopt($curlHandle, CURLOPT_POST, true);
|
||
|
$arr = buildCustomPostFields($httpRequest->dataToPost);
|
||
|
array_push($headers, 'Expect: 100-continue');
|
||
|
array_push($headers, 'Content-Type: multipart/form-data; boundary=' . $arr[0]);
|
||
|
curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $arr[1]);
|
||
|
}
|
||
|
curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $headers);
|
||
|
|
||
|
curl_multi_add_handle($this->curlMultiHandle, $curlHandle);
|
||
|
|
||
|
|
||
|
$this->curlHandleInfo[$this->sequence]['handle'] = $curlHandle;
|
||
|
$this->curlHandleInfo[$this->sequence]['done'] = $done;
|
||
|
$this->curlHandleInfo[$this->sequence]['request'] = $httpRequest;
|
||
|
}
|
||
|
|
||
|
public function performSendingRequest() {
|
||
|
for (;;) {
|
||
|
$active = null;
|
||
|
|
||
|
do {
|
||
|
$mrc = curl_multi_exec($this->curlMultiHandle, $active);
|
||
|
$info = curl_multi_info_read($this->curlMultiHandle);
|
||
|
if ($info !== false) {
|
||
|
$this->processResult($info);
|
||
|
}
|
||
|
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
|
||
|
|
||
|
while ($active && $mrc == CURLM_OK) {
|
||
|
if (curl_multi_select($this->curlMultiHandle) == -1) {
|
||
|
usleep(1);
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
$mrc = curl_multi_exec($this->curlMultiHandle, $active);
|
||
|
$info = curl_multi_info_read($this->curlMultiHandle);
|
||
|
if ($info !== false) {
|
||
|
$this->processResult($info);
|
||
|
}
|
||
|
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
|
||
|
}
|
||
|
|
||
|
if (count($this->curlHandleInfo) == 0) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private function processResult($info) {
|
||
|
$result = $info['result'];
|
||
|
$handle = $info['handle'];
|
||
|
$sequence = 0;
|
||
|
|
||
|
foreach ($this->curlHandleInfo as $key => $info) {
|
||
|
if ($info['handle'] === $handle) {
|
||
|
$sequence = $key;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$request = $this->curlHandleInfo[$sequence]['request'];
|
||
|
$done = $this->curlHandleInfo[$sequence]['done'];
|
||
|
$response = new HttpResponse();
|
||
|
|
||
|
if ($result !== CURLE_OK) {
|
||
|
$response->curlErrorCode = $result;
|
||
|
$response->curlErrorMessage = curl_error($handle);
|
||
|
|
||
|
call_user_func($done, $request, $response);
|
||
|
} else {
|
||
|
$responseStr = curl_multi_getcontent($handle);
|
||
|
$headerSize = curl_getinfo($handle, CURLINFO_HEADER_SIZE);
|
||
|
$headerStr = substr($responseStr, 0, $headerSize);
|
||
|
$body = substr($responseStr, $headerSize);
|
||
|
|
||
|
$response->curlErrorCode = curl_errno($handle);
|
||
|
$response->curlErrorMessage = curl_error($handle);
|
||
|
$response->statusCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
|
||
|
$headLines = explode("\r\n", $headerStr);
|
||
|
foreach ($headLines as $head) {
|
||
|
$arr = explode(':', $head);
|
||
|
if (count($arr) >= 2) {
|
||
|
$response->headers[trim($arr[0])] = trim($arr[1]);
|
||
|
}
|
||
|
}
|
||
|
$response->body = $body;
|
||
|
|
||
|
call_user_func($done, $request, $response);
|
||
|
}
|
||
|
|
||
|
unset($this->curlHandleInfo[$sequence]);
|
||
|
curl_multi_remove_handle($this->curlMultiHandle, $handle);
|
||
|
|
||
|
array_push($this->idleCurlHandle, $handle);
|
||
|
}
|
||
|
|
||
|
private function resetCurl($handle) {
|
||
|
if (function_exists('curl_reset')) {
|
||
|
curl_reset($handle);
|
||
|
} else {
|
||
|
curl_setopt($handler, CURLOPT_URL, '');
|
||
|
curl_setopt($handler, CURLOPT_HTTPHEADER, array());
|
||
|
curl_setopt($handler, CURLOPT_POSTFIELDS, array());
|
||
|
curl_setopt($handler, CURLOPT_TIMEOUT, 0);
|
||
|
curl_setopt($handler, CURLOPT_SSL_VERIFYPEER, false);
|
||
|
curl_setopt($handler, CURLOPT_SSL_VERIFYHOST, 0);
|
||
|
}
|
||
|
}
|
||
|
}
|