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; } }