228 lines
7.9 KiB
PHP
228 lines
7.9 KiB
PHP
<?php
|
|
|
|
namespace Yurun\Util\Swoole\Guzzle\Ring;
|
|
|
|
use GuzzleHttp\Ring\Core;
|
|
use GuzzleHttp\Ring\Exception\RingException;
|
|
use GuzzleHttp\Ring\Future\CompletedFutureArray;
|
|
use Swoole\Coroutine;
|
|
use Yurun\Util\HttpRequest;
|
|
use Yurun\Util\YurunHttp;
|
|
use Yurun\Util\YurunHttp\Http\Psr7\Uri;
|
|
use Yurun\Util\YurunHttp\Http\Response;
|
|
|
|
class SwooleHandler
|
|
{
|
|
/**
|
|
* 选项集合.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $options;
|
|
|
|
public function __construct(array $options = [])
|
|
{
|
|
$this->options = $options;
|
|
}
|
|
|
|
/**
|
|
* @param array $request
|
|
*
|
|
* @return CompletedFutureArray
|
|
*/
|
|
public function __invoke(array $request)
|
|
{
|
|
$httpRequest = new HttpRequest();
|
|
$yurunResponse = $this->getYurunResponse($httpRequest, $request);
|
|
$response = $this->getResponse($httpRequest, $yurunResponse);
|
|
|
|
return new CompletedFutureArray($response);
|
|
}
|
|
|
|
/**
|
|
* 获取 YurunHttp Response.
|
|
*
|
|
* @param \Yurun\Util\HttpRequest $httpRequest
|
|
* @param array $request
|
|
*
|
|
* @return \Yurun\Util\YurunHttp\Http\Response
|
|
*/
|
|
protected function getYurunResponse(HttpRequest $httpRequest, array $request): Response
|
|
{
|
|
foreach ($request['client'] ?? [] as $key => $value)
|
|
{
|
|
switch ($key)
|
|
{
|
|
// Violating PSR-4 to provide more room.
|
|
case 'verify':
|
|
if ($httpRequest->isVerifyCA = $value && \is_string($value))
|
|
{
|
|
if (!file_exists($value))
|
|
{
|
|
throw new \InvalidArgumentException("SSL CA bundle not found: $value");
|
|
}
|
|
$httpRequest->caCert = $value;
|
|
}
|
|
break;
|
|
case 'decode_content':
|
|
break;
|
|
case 'save_to':
|
|
break;
|
|
case 'timeout':
|
|
$httpRequest->timeout = $value * 1000;
|
|
break;
|
|
case 'connect_timeout':
|
|
$httpRequest->connectTimeout = $value * 1000;
|
|
break;
|
|
case 'proxy':
|
|
if (!\is_array($value))
|
|
{
|
|
$uri = new Uri($value);
|
|
}
|
|
elseif (isset($request['scheme']))
|
|
{
|
|
$scheme = $request['scheme'];
|
|
if (isset($value[$scheme]))
|
|
{
|
|
$uri = new Uri($value[$scheme]);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
$httpRequest->proxy($uri->getHost(), Uri::getServerPort($uri), $uri->getScheme());
|
|
break;
|
|
|
|
case 'cert':
|
|
if (\is_array($value))
|
|
{
|
|
$httpRequest->certPassword = $value[1];
|
|
$value = $value[0];
|
|
}
|
|
if (!file_exists($value))
|
|
{
|
|
throw new \InvalidArgumentException("SSL certificate not found: {$value}");
|
|
}
|
|
$httpRequest->certType = $value;
|
|
break;
|
|
case 'ssl_key':
|
|
if (\is_array($value))
|
|
{
|
|
$httpRequest->keyPassword = $value[1];
|
|
// $options[CURLOPT_SSLKEYPASSWD] = $value[1];
|
|
$value = $value[0];
|
|
}
|
|
|
|
if (!file_exists($value))
|
|
{
|
|
throw new \InvalidArgumentException("SSL private key not found: {$value}");
|
|
}
|
|
$httpRequest->keyPath = $value;
|
|
break;
|
|
case 'progress':
|
|
break;
|
|
case 'debug':
|
|
break;
|
|
}
|
|
}
|
|
// headers
|
|
foreach ($request['headers'] as $name => $list)
|
|
{
|
|
$httpRequest->header($name, implode(', ', $list));
|
|
}
|
|
if (isset($httpRequest->headers['Content-Length']))
|
|
{
|
|
unset($httpRequest->headers['Content-Length']);
|
|
}
|
|
// request
|
|
$method = $request['http_method'] ?? 'GET';
|
|
$url = Core::url($request);
|
|
if (isset($request['client']['curl'][\CURLOPT_PORT]))
|
|
{
|
|
$uri = new Uri($url);
|
|
$uri = $uri->withPort($request['client']['curl'][\CURLOPT_PORT]);
|
|
$url = (string) $uri;
|
|
}
|
|
if (isset($request['client']['curl'][\CURLOPT_USERPWD]))
|
|
{
|
|
$httpRequest->userPwd(...explode(':', $request['client']['curl'][\CURLOPT_USERPWD], 2));
|
|
}
|
|
$body = Core::body($request);
|
|
$httpRequest->url = $url;
|
|
$httpRequest->requestBody((string) $body);
|
|
$yurunRequest = $httpRequest->buildRequest(null, null, $method);
|
|
|
|
return YurunHttp::send($yurunRequest, Coroutine::getuid() > -1 ? \Yurun\Util\YurunHttp\Handler\Swoole::class : \Yurun\Util\YurunHttp\Handler\Curl::class);
|
|
}
|
|
|
|
/**
|
|
* 获取响应数组.
|
|
*
|
|
* @param \Yurun\Util\HttpRequest $httpRequest
|
|
* @param \Yurun\Util\YurunHttp\Http\Response $yurunResponse
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function getResponse(HttpRequest $httpRequest, Response $yurunResponse): array
|
|
{
|
|
$uri = new Uri($httpRequest->url);
|
|
$transferStatus = [
|
|
'url' => $httpRequest->url,
|
|
'content_type' => $yurunResponse->getHeaderLine('content-type'),
|
|
'http_code' => $yurunResponse->getStatusCode(),
|
|
'header_size' => 0,
|
|
'request_size' => 0,
|
|
'filetime' => 0,
|
|
'ssl_verify_result' => true,
|
|
'redirect_count' => 0,
|
|
'total_time' => $yurunResponse->totalTime(),
|
|
'namelookup_time' => 0,
|
|
'connect_time' => 0,
|
|
'pretransfer_time' => 0,
|
|
'size_upload' => 0,
|
|
'size_download' => 0,
|
|
'speed_download' => 0,
|
|
'speed_upload' => 0,
|
|
'download_content_length' => 0,
|
|
'upload_content_length' => 0,
|
|
'starttransfer_time' => 0,
|
|
'redirect_time' => 0,
|
|
'certinfo' => '',
|
|
'primary_ip' => $uri->getHost(),
|
|
'primary_port' => Uri::getServerPort($uri),
|
|
'local_ip' => '127.0.0.1',
|
|
'local_port' => 12345,
|
|
];
|
|
if (!$yurunResponse->success)
|
|
{
|
|
$error = new RingException($yurunResponse->getError());
|
|
}
|
|
$version = $yurunResponse->getProtocolVersion();
|
|
$status = $yurunResponse->getStatusCode();
|
|
$reason = $yurunResponse->getReasonPhrase();
|
|
$body = fopen('php://temp', 'r+');
|
|
fwrite($body, (string) $yurunResponse->getBody());
|
|
fseek($body, 0);
|
|
$response = [
|
|
'curl' => [
|
|
'errno' => 0,
|
|
'error' => '',
|
|
],
|
|
'transfer_stats' => $transferStatus,
|
|
'effective_url' => $transferStatus['url'],
|
|
'headers' => $yurunResponse->getHeaders(),
|
|
'version' => $version,
|
|
'status' => $status,
|
|
'reason' => $reason,
|
|
'body' => $body,
|
|
];
|
|
if (isset($error))
|
|
{
|
|
$response['error'] = $error;
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
}
|