From 18b44b32f2f1f249adfc2f6b04bad2cf7d6e1c6d Mon Sep 17 00:00:00 2001 From: xl Date: Wed, 12 Jul 2023 21:38:27 +0800 Subject: [PATCH] qqq --- ClientAbstracts.php | 183 +++++++------------- CoroutineClient.php | 29 +--- CurlClient.php | 409 ++++++++++++++++++++++---------------------- IClient.php | 80 +++++---- TSwooleClient.php | 4 +- composer.json | 4 +- 6 files changed, 312 insertions(+), 397 deletions(-) diff --git a/ClientAbstracts.php b/ClientAbstracts.php index 49d8b7e..42f8caf 100644 --- a/ClientAbstracts.php +++ b/ClientAbstracts.php @@ -5,12 +5,7 @@ namespace Kiri; use Closure; -use Exception; -use JetBrains\PhpStorm\Pure; -use Kiri\Core\Help; -use Kiri\Di\Context; -use Kiri\Router\Constrict\Stream; -use Psr\Http\Message\StreamInterface; +use Swoole\Coroutine; use Swoole\Coroutine\System; defined('SPLIT_URL') or define('SPLIT_URL', '/(http[s]?:\/\/)?(([\w\-_]+\.)+\w+(:\d+)?)((\/[a-zA-Z0-9\-]+)+[\/]?(\?[a-zA-Z]+=.*)?)?/'); @@ -47,6 +42,7 @@ abstract class ClientAbstracts implements IClient private string $ca = ''; private int $port = 80; + protected int $num = 0; private ?array $_responseHeader = []; @@ -68,7 +64,7 @@ abstract class ClientAbstracts implements IClient protected ?string $body; - private ?StreamInterface $_data = NULL; + private string|array|null $_data = NULL; private int $connect_timeout = 1; @@ -214,21 +210,21 @@ abstract class ClientAbstracts implements IClient } - /** - * @param string $path - * @param array $params - */ - public function post(string $path, array $params = []): void + /** + * @param string $path + * @param array|string $params + */ + public function post(string $path, array|string $params = []): void { $this->request(self::POST, $path, $params); } - /** - * @param string $path - * @param array $params - */ - public function put(string $path, array $params = []): void + /** + * @param string $path + * @param array|string $params + */ + public function put(string $path, array|string $params = []): void { $this->request(self::PUT, $path, $params); } @@ -245,58 +241,61 @@ abstract class ClientAbstracts implements IClient } - /** - * @param string $path - * @param array $params - */ - public function head(string $path, array $params = []): void + /** + * @param string $path + * @param array|string $params + */ + public function head(string $path, array|string $params = []): void { $this->request(self::HEAD, $path, $params); } - /** - * @param string $path - * @param array $params - */ - public function get(string $path, array $params = []): void + /** + * @param string $path + * @param array|string $params + */ + public function get(string $path, array|string $params = []): void { + if (is_array($params)) { + $params = http_build_query($params); + } $this->request(self::GET, $path, $params); } - /** - * @param string $path - * @param array $params - */ - public function option(string $path, array $params = []): void + /** + * @param string $path + * @param array|string $params + */ + public function option(string $path, array|string $params = []): void { $this->request(self::OPTIONS, $path, $params); } - /** - * @param string $path - * @param array $params - */ - public function delete(string $path, array $params = []): void + /** + * @param string $path + * @param array|string $params + */ + public function delete(string $path, array|string $params = []): void { $this->request(self::DELETE, $path, $params); } - /** - * @param string $path - * @param array $params - */ - public function options(string $path, array $params = []): void + /** + * @param string $path + * @param array|string $params + */ + public function options(string $path, array|string $params = []): void { $this->request(self::OPTIONS, $path, $params); } - /** - * @param string $path - * @param array $params - */ - public function upload(string $path, array $params = []): void + /** + * @param string $path + * @param array|string $params + */ + public function upload(string $path, array|string $params = []): void { $this->request(self::UPLOAD, $path, $params); } @@ -313,7 +312,7 @@ abstract class ClientAbstracts implements IClient /** * @return int */ - #[Pure] protected function getHostPort(): int + protected function getHostPort(): int { if (!empty($this->getPort())) { return $this->getPort(); @@ -332,7 +331,7 @@ abstract class ClientAbstracts implements IClient { $this->host = $host; if (!preg_match('/(\d{1,3}\.){3}\d{1,3}/', $host)) { - if (Context::inCoroutine()) { + if (class_exists(Coroutine::class) && Coroutine::getCid() > -1) { $this->host = System::gethostbyname($host); } return $this->withAddedHeader('Host', $host); @@ -535,7 +534,7 @@ abstract class ClientAbstracts implements IClient /** * @return int */ - #[Pure] public function getPort(): int + public function getPort(): int { if ($this->isSSL()) { return 443; @@ -557,26 +556,20 @@ abstract class ClientAbstracts implements IClient } - /** - * @return StreamInterface - */ - public function getData(): StreamInterface + /** + * @return string|null + */ + public function getData(): ?string { - if (!$this->_data) { - $this->_data = new Stream(); - } return $this->_data; } /** - * @param string|StreamInterface $data + * @param string|null $data * @return ClientAbstracts */ - public function withBody(string|StreamInterface $data): static + public function withBody(?string $data): static { - if (is_string($data)) { - $data = new Stream($data); - } $this->_data = $data; return $this; } @@ -650,68 +643,18 @@ abstract class ClientAbstracts implements IClient */ protected function mergeParams($newData): ?string { - if (!is_string($newData)) { - return $this->toRequest($newData); - } + if (is_array($newData)) { + return json_encode($newData,JSON_UNESCAPED_UNICODE); + } return (string)$newData; } - /** - * @param $data - * @return string - */ - protected function toRequest($data): string - { - if (is_string($data)) { - return $data; - } - $contentType = 'application/x-www-form-urlencoded'; - if (isset($this->header['Content-Type'])) { - $contentType = $this->header['Content-Type']; - } else if (isset($this->header['content-type'])) { - $contentType = $this->header['content-type']; - } - if (str_contains($contentType, 'json')) { - return Help::toJson($data); - } else if (str_contains($contentType, 'xml')) { - return Help::toXml($data); - } else { - return http_build_query($data); - } - } - - - /** - * @param $data - * @param $body - * @return array|string|null - * @throws Exception - */ - protected function resolve($data, $body): array|string|null - { - if (is_array($body)) { - return $body; - } - $type = $data['content-type'] ?? $data['Content-Type'] ?? 'text/html'; - if (str_contains($type, 'text/html')) { - return $body; - } else if (str_contains($type, 'json')) { - return json_decode($body, TRUE); - } else if (str_contains($type, 'xml')) { - return Help::xmlToArray($body); - } else if (str_contains($type, 'plain')) { - return Help::toArray($body); - } - return $body; - } - - /** * @return bool * check isPost Request */ - #[Pure] protected function isPost(): bool + protected function isPost(): bool { return strtolower($this->method) === self::POST; } @@ -720,7 +663,7 @@ abstract class ClientAbstracts implements IClient * @return bool * check isPost Request */ - #[Pure] protected function isUpload(): bool + protected function isUpload(): bool { return strtolower($this->method) === self::UPLOAD; } @@ -731,7 +674,7 @@ abstract class ClientAbstracts implements IClient * * check isGet Request */ - #[Pure] protected function isGet(): bool + protected function isGet(): bool { return strtolower($this->method) === self::GET; } @@ -742,7 +685,7 @@ abstract class ClientAbstracts implements IClient * @return array|string * 将请求参数进行编码 */ - #[Pure] protected function paramEncode($arr): array|string + protected function paramEncode($arr): array|string { if (!is_array($arr)) { return $arr; @@ -762,7 +705,7 @@ abstract class ClientAbstracts implements IClient * @param string $string * @return array */ - #[Pure] protected function matchHost(string $string): array + protected function matchHost(string $string): array { return [$this->host, $this->isSSL(), $string]; } diff --git a/CoroutineClient.php b/CoroutineClient.php index 0f53bec..288acff 100644 --- a/CoroutineClient.php +++ b/CoroutineClient.php @@ -10,10 +10,6 @@ declare(strict_types=1); namespace Kiri; use Exception; -use Kiri; -use Kiri\Abstracts\Logger; -use Kiri\Di\Context; -use Psr\Log\LoggerInterface; use Swoole\Coroutine\Http\Client as SwowClient; /** @@ -28,11 +24,11 @@ class CoroutineClient extends ClientAbstracts /** * @param string $method * @param $path - * @param array $params + * @param array|string $params * @return void * @throws Exception */ - public function request(string $method, $path, array $params = []): void + public function request(string $method, $path, array|string $params = []): void { if (!str_starts_with($path, '/')) { $path = '/' . $path; @@ -70,10 +66,6 @@ class CoroutineClient extends ClientAbstracts $this->execute($url, $data); } catch (\Throwable $exception) { - Kiri::getDi()->get(Logger::class)->error('rpc', []); - - Kiri::getLogger()->error(throwable($exception)); - $this->setStatusCode(-1); $this->setBody(jTraceEx($exception)); } @@ -89,17 +81,6 @@ class CoroutineClient extends ClientAbstracts private function execute($path, $data): void { $this->client->execute($this->setParams($path, $data)); - if ($this->client->statusCode < 1) { - $logger = Kiri::getDi()->get(LoggerInterface::class); - $errMsg = sprintf("%s://%s:%s/%s -> error: %s", $this->isSSL() ? "https" : "http", - $this->getHost(), $this->getPort(), $path, $this->client->errMsg); - - if (!empty($data)) { - $errMsg .= print_r($data, true); - } - - $logger->error($errMsg); - } if (in_array($this->client->getStatusCode(), [502, 404])) { $this->retry($path, $data); } else { @@ -118,13 +99,11 @@ class CoroutineClient extends ClientAbstracts */ private function retry($path, $data): void { - if (Context::increment('retry') <= $this->retryNum) { + if (($this->num += 1) <= $this->retryNum) { sleep($this->retryTimeout); $this->execute($path, $data); } else { - Context::remove('retry'); - $this->setStatusCode($this->client->statusCode); $this->setBody($this->client->errMsg); } @@ -157,7 +136,7 @@ class CoroutineClient extends ClientAbstracts */ private function setParams($path, $data): string { - $content = $this->getData()->getContents(); + $content = $this->getData(); if (!empty($content)) { $this->client->setData($content); } diff --git a/CurlClient.php b/CurlClient.php index cefb828..37a21d4 100644 --- a/CurlClient.php +++ b/CurlClient.php @@ -5,8 +5,6 @@ namespace Kiri; use Exception; -use JetBrains\PhpStorm\Pure; -use Kiri\Di\Context; /** @@ -16,216 +14,217 @@ use Kiri\Di\Context; class CurlClient extends ClientAbstracts { - /** - * @param $method - * @param $path - * @param array $params - * @throws Exception - */ - public function request($method, $path, array $params = []): void - { - if (!str_starts_with($path, '/')) { - $path = '/' . $path; - } - if ($method == self::GET) { - $path = $this->joinGetParams($path, $params); - } - - $this->getCurlHandler($path, $method, $params); - - $this->execute(); - } - - - /** - * @param $path - * @param $method - * @param $params - * @throws Exception - */ - private function getCurlHandler($path, $method, $params): void - { - $host = $this->isSSL() ? 'https://' . $this->getHost() : 'http://' . $this->getHost(); - if ($this->getPort() != 443 && $this->getPort() != 80) { - $host .= ':' . $this->getPort(); - } - $this->do(curl_init($host . $path), $host . $path, $method); - if ($this->isSSL()) { - $this->curlHandlerSslSet(); - } - $contents = $this->getData()->getContents(); - if (empty($params) && empty($contents)) { - return; - } - if (!empty($contents)) { - curl_setopt($this->client, CURLOPT_POSTFIELDS, $contents); - } else if ($method === self::POST) { - curl_setopt($this->client, CURLOPT_POSTFIELDS, $this->mergeParams($params)); - } else if ($method === self::UPLOAD) { - curl_setopt($this->client, CURLOPT_POSTFIELDS, $params); - } - } - - - /** - * @return void - * @throws Exception - */ - private function curlHandlerSslSet(): void - { - if (!empty($this->getSslKeyFile()) && file_exists($this->getSslKeyFile())) { - curl_setopt($this->client, CURLOPT_SSLKEY, $this->getSslKeyFile()); - } - if (!empty($this->getSslCertFile()) && file_exists($this->getSslCertFile())) { - curl_setopt($this->client, CURLOPT_SSLCERT, $this->getSslCertFile()); - } - } - - - /** - * @param $resource - * @param $path - * @param $method - * @throws Exception - */ - private function do($resource, $path, $method): void - { - curl_setopt($resource, CURLOPT_URL, $path); - curl_setopt($resource, CURLOPT_TIMEOUT, $this->getTimeout()); // 超时设置 - curl_setopt($resource, CURLOPT_CONNECTTIMEOUT, $this->getConnectTimeout()); // 超时设置 - curl_setopt($resource, CURLOPT_HEADER, TRUE); - curl_setopt($resource, CURLOPT_FAILONERROR, TRUE); - curl_setopt($resource, CURLOPT_HTTPHEADER, $this->parseHeaderMat()); - if (defined('CURLOPT_SSL_FALSESTART')) { - curl_setopt($resource, CURLOPT_SSL_FALSESTART, TRUE); - } - curl_setopt($resource, CURLOPT_FORBID_REUSE, FALSE); - curl_setopt($resource, CURLOPT_FRESH_CONNECT, FALSE); - if (!empty($this->getAgent())) { - curl_setopt($resource, CURLOPT_USERAGENT, $this->getAgent()); - } - curl_setopt($resource, CURLOPT_NOBODY, FALSE); - curl_setopt($resource, CURLOPT_RETURNTRANSFER, TRUE);//返回内容 - curl_setopt($resource, CURLOPT_FOLLOWLOCATION, TRUE);// 跟踪重定向 - curl_setopt($resource, CURLOPT_ENCODING, 'gzip,deflate'); - if ($method === self::POST || $method == self::UPLOAD) { - curl_setopt($resource, CURLOPT_POST, 1); - } - curl_setopt($resource, CURLOPT_CUSTOMREQUEST, strtoupper($method)); - $this->client = $resource; - if (!empty($this->caPath)) { - curl_setopt($this->client, CURLOPT_CAINFO, $this->caPath); - } - } - - - private string $caPath = ''; - - - /** - * @param $path - * @return $this - */ - public function withCAInfo($path): static - { - $this->caPath = $path; - return $this; - } - - - /** - * @throws Exception - */ - private function execute(): void - { - $output = curl_exec($this->client); - if ($output !== FALSE) { - $this->explode($output); - } else { - $this->setStatusCode(curl_errno($this->client)); - $this->setBody(curl_error($this->client)); - } - } - - - /** - * @return void - * @throws Exception - */ - private function retry(): void + /** + * @param $method + * @param $path + * @param array|string $params + * @throws Exception + */ + public function request($method, $path, array|string $params = []): void { - if (Context::increment('retry') <= $this->retryNum) { - sleep($this->retryTimeout); + if (!str_starts_with($path, '/')) { + $path = '/' . $path; + } + if ($method == self::GET) { + $path = $this->joinGetParams($path, $params); + } - $this->execute(); - } else { - Context::remove('retry'); + $this->getCurlHandler($path, $method, $params); - $this->setStatusCode(curl_errno($this->client)); - $this->setBody(curl_error($this->client)); - } - } + $this->execute(); + } - /** - * - */ - public function close(): void - { - curl_close($this->client); - } + /** + * @param $path + * @param $method + * @param $params + * @throws Exception + */ + private function getCurlHandler($path, $method, $params): void + { + $host = $this->isSSL() ? 'https://' . $this->getHost() : 'http://' . $this->getHost(); + if ($this->getPort() != 443 && $this->getPort() != 80) { + $host .= ':' . $this->getPort(); + } + $this->do(curl_init($host . $path), $host . $path, $method); + if ($this->isSSL()) { + $this->curlHandlerSslSet(); + } + $contents = $this->getData(); + if (empty($params) && empty($contents)) { + return; + } + if (!empty($contents)) { + curl_setopt($this->client, CURLOPT_POSTFIELDS, $contents); + } else if ($method === self::UPLOAD) { + curl_setopt($this->client, CURLOPT_POSTFIELDS, $params); + } else if ($method === self::POST) { + if (is_array($params)) { + $params = http_build_query($params); + } + curl_setopt($this->client, CURLOPT_POSTFIELDS, $params); + } + } - /** - * @param $output - * @return void - * @throws Exception - */ - private function explode($output): void - { - [$header, $body] = explode("\r\n\r\n", $output, 2); - if ($header == 'HTTP/1.1 100 Continue') { - [$header, $body] = explode("\r\n\r\n", $body, 2); - } - - $header = explode("\r\n", $header); - $status = explode(' ', array_shift($header)); - - $statusCode = intval($status[1]); - if (in_array($statusCode, [502, 404])) { - $this->retry(); - } else { - $this->setStatusCode($statusCode); - $this->setBody($body); - $this->setResponseHeader($header); - } - } - - /** - * @param $headers - * @return array - */ - private function headerFormat($headers): array - { - $_tmp = []; - foreach ($headers as $val) { - $trim = explode(': ', trim($val)); - - $_tmp[strtolower($trim[0])] = [$trim[1] ?? '']; - } - return $_tmp; - } + /** + * @return void + * @throws Exception + */ + private function curlHandlerSslSet(): void + { + if (!empty($this->getSslKeyFile()) && file_exists($this->getSslKeyFile())) { + curl_setopt($this->client, CURLOPT_SSLKEY, $this->getSslKeyFile()); + } + if (!empty($this->getSslCertFile()) && file_exists($this->getSslCertFile())) { + curl_setopt($this->client, CURLOPT_SSLCERT, $this->getSslCertFile()); + } + } - /** - * @return array - */ - #[Pure] private function parseHeaderMat(): array - { - $headers = []; - foreach ($this->getHeader() as $key => $val) { - $headers[$key] = $key . ': ' . $val; - } - return array_values($headers); - } + /** + * @param $resource + * @param $path + * @param $method + * @throws Exception + */ + private function do($resource, $path, $method): void + { + curl_setopt($resource, CURLOPT_URL, $path); + curl_setopt($resource, CURLOPT_TIMEOUT, $this->getTimeout()); // 超时设置 + curl_setopt($resource, CURLOPT_CONNECTTIMEOUT, $this->getConnectTimeout()); // 超时设置 + curl_setopt($resource, CURLOPT_HEADER, TRUE); + curl_setopt($resource, CURLOPT_FAILONERROR, TRUE); + curl_setopt($resource, CURLOPT_HTTPHEADER, $this->parseHeaderMat()); + if (defined('CURLOPT_SSL_FALSESTART')) { + curl_setopt($resource, CURLOPT_SSL_FALSESTART, TRUE); + } + curl_setopt($resource, CURLOPT_FORBID_REUSE, FALSE); + curl_setopt($resource, CURLOPT_FRESH_CONNECT, FALSE); + if (!empty($this->getAgent())) { + curl_setopt($resource, CURLOPT_USERAGENT, $this->getAgent()); + } + curl_setopt($resource, CURLOPT_NOBODY, FALSE); + curl_setopt($resource, CURLOPT_RETURNTRANSFER, TRUE);//返回内容 + curl_setopt($resource, CURLOPT_FOLLOWLOCATION, TRUE);// 跟踪重定向 + curl_setopt($resource, CURLOPT_ENCODING, 'gzip,deflate'); + if ($method === self::POST || $method == self::UPLOAD) { + curl_setopt($resource, CURLOPT_POST, 1); + } + curl_setopt($resource, CURLOPT_CUSTOMREQUEST, strtoupper($method)); + $this->client = $resource; + if (!empty($this->caPath)) { + curl_setopt($this->client, CURLOPT_CAINFO, $this->caPath); + } + } + + + private string $caPath = ''; + + + /** + * @param $path + * @return $this + */ + public function withCAInfo($path): static + { + $this->caPath = $path; + return $this; + } + + + /** + * @throws Exception + */ + private function execute(): void + { + $output = curl_exec($this->client); + if ($output !== FALSE) { + $this->explode($output); + } else { + $this->setStatusCode(curl_errno($this->client)); + $this->setBody(curl_error($this->client)); + } + } + + + /** + * @return void + * @throws Exception + */ + private function retry(): void + { + if (($this->num += 1) <= $this->retryNum) { + sleep($this->retryTimeout); + + $this->execute(); + } else { + $this->setStatusCode(curl_errno($this->client)); + $this->setBody(curl_error($this->client)); + } + } + + + /** + * + */ + public function close(): void + { + curl_close($this->client); + } + + + /** + * @param $output + * @return void + * @throws Exception + */ + private function explode($output): void + { + [$header, $body] = explode("\r\n\r\n", $output, 2); + if ($header == 'HTTP/1.1 100 Continue') { + [$header, $body] = explode("\r\n\r\n", $body, 2); + } + + $header = explode("\r\n", $header); + $status = explode(' ', array_shift($header)); + + $statusCode = intval($status[1]); + if (in_array($statusCode, [502, 404])) { + $this->retry(); + } else { + $this->setStatusCode($statusCode); + $this->setBody($body); + $this->setResponseHeader($header); + } + } + + /** + * @param $headers + * @return array + */ + private function headerFormat($headers): array + { + $_tmp = []; + foreach ($headers as $val) { + $trim = explode(': ', trim($val)); + + $_tmp[strtolower($trim[0])] = [$trim[1] ?? '']; + } + return $_tmp; + } + + + /** + * @return array + */ + private function parseHeaderMat(): array + { + $headers = []; + foreach ($this->getHeader() as $key => $val) { + $headers[$key] = $key . ': ' . $val; + } + return array_values($headers); + } } diff --git a/IClient.php b/IClient.php index faed426..96daea5 100644 --- a/IClient.php +++ b/IClient.php @@ -5,25 +5,23 @@ namespace Kiri; use Closure; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; interface IClient { - /** - * @param string $path - * @param array $params - */ - public function get(string $path, array $params = []): void; + /** + * @param string $path + * @param array|string $params + */ + public function get(string $path, array|string $params = []): void; - /** - * @param string $path - * @param array $params - */ - public function post(string $path, array $params = []): void; + /** + * @param string $path + * @param array|string $params + */ + public function post(string $path, array|string $params = []): void; /** @@ -32,47 +30,47 @@ interface IClient public function close(): void; - /** - * @param string $path - * @param array $params - */ - public function delete(string $path, array $params = []): void; + /** + * @param string $path + * @param array|string $params + */ + public function delete(string $path, array|string $params = []): void; - /** - * @param string $path - * @param array $params - */ - public function options(string $path, array $params = []): void; + /** + * @param string $path + * @param array|string $params + */ + public function options(string $path, array|string $params = []): void; - /** - * @param string $path - * @param array $params - */ - public function upload(string $path, array $params = []): void; + /** + * @param string $path + * @param array|string $params + */ + public function upload(string $path, array|string $params = []): void; - /** - * @param string $path - * @param array $params - */ - public function put(string $path, array $params = []): void; + /** + * @param string $path + * @param array|string $params + */ + public function put(string $path, array|string $params = []): void; - /** - * @param string $path - * @param array $params - */ - public function head(string $path, array $params = []): void; + /** + * @param string $path + * @param array|string $params + */ + public function head(string $path, array|string $params = []): void; /** * @param string $method * @param string $path - * @param array $params + * @param array|string $params */ - public function request(string $method, string $path, array $params = []): void; + public function request(string $method, string $path, array|string $params = []): void; /** @@ -154,10 +152,10 @@ interface IClient /** - * @param string|StreamInterface $data + * @param string $data * @return static */ - public function withBody(string|StreamInterface $data): static; + public function withBody(string $data): static; /** diff --git a/TSwooleClient.php b/TSwooleClient.php index cf12a5d..5ffb5a4 100644 --- a/TSwooleClient.php +++ b/TSwooleClient.php @@ -2,8 +2,6 @@ namespace Kiri; -use JetBrains\PhpStorm\Pure; - trait TSwooleClient { @@ -11,7 +9,7 @@ trait TSwooleClient /** * @return array */ - #[Pure] private function settings(): array + private function settings(): array { $sslCert = $this->getSslCertFile(); $sslKey = $this->getSslKeyFile(); diff --git a/composer.json b/composer.json index 0a7dc98..7662fbd 100644 --- a/composer.json +++ b/composer.json @@ -11,9 +11,7 @@ "require": { "php": ">=8.0", "ext-json": "*", - "ext-swoole": "*", - "psr/http-client": "^1.0", - "psr/http-message": "^1.0" + "ext-swoole": "*" }, "autoload": { "psr-4": {