diff --git a/AsyncClient.php b/AsyncClient.php index 36ae3ec..2923fda 100644 --- a/AsyncClient.php +++ b/AsyncClient.php @@ -1,178 +1,178 @@ -withMethod($method) - ->coroutine( - $this->matchHost($path), - $this->paramEncode($params) - ); - } - - - /** - * @param $path - * @return $this - */ - public function withCAInfo($path): static - { - return $this; - } - - /** - * @param $url - * @param array|string $data - * @throws Exception 使用swoole协程方式请求 - */ - private function coroutine($url, array|string $data = []): void - { - try { - $this->generate_client($data, ...$url); - } catch (\Throwable $exception) { - Kiri::getDi()->get(Logger::class)->error('rpc', [$exception]); - $this->setStatusCode(-1); - $this->setBody(jTraceEx($exception)); - } - } - - - /** - * @param $data - * @param $host - * @param $isHttps - * @param $path - * @throws Exception - */ - private function generate_client($data, $host, $isHttps, $path): void - { - $this->client = new SwowClient(SWOOLE_TCP, FALSE); - if (!$this->client->connect($host, $this->getPort())) { - throw new Exception('链接失败'); - } - if ($isHttps || $this->isSSL()) { - $this->client->enableSSL(); - } - $this->client->set(array_merge($this->settings(), ['open_http_protocol' => true])); - if (!empty($this->getAgent())) { - $this->withAddedHeader('User-Agent', $this->getAgent()); - } - - $path = $this->setParams($path, $data); - - $this->withAddedHeader('Accept', ' text/html,application/xhtml+xml,application/json,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'); -// $this->withAddedHeader('Accept-Encoding', 'gzip'); - $this->withAddedHeader('Content-Length', $this->getData()->getSize()); - - $this->execute($path, $this->getData()->getContents()); - } - - - /** - * @param string $path - * @param string $content - * @return void - */ - private function execute(string $path, string $content) - { - $array = []; - $array[] = strtoupper($this->getMethod()) . ' ' . $path . ' HTTP/1.1'; - if (!empty($this->getHeader())) { - foreach ($this->getHeader() as $key => $value) { - $array[] = sprintf('%s: %s', $key, $value); - } - } - $this->client->send(implode("\r\n", $array) . "\r\n\r\n" . $content); - $receive = $this->client->recv(); - - [$header, $body] = explode("\r\n\r\n", $receive); - - $header = explode("\r\n", $header); - $status = array_shift($header); - - $this->setStatusCode(intval(explode(' ', $status)[1])); - $this->parseResponseHeaders($header); - $this->setBody($body); - } - - - private function chunked() - { - - } - - - /** - * @param array $headers - * @return void - */ - private function parseResponseHeaders(array $headers) - { - $array = []; - foreach ($headers as $header) { - [$key, $value] = explode(': ', $header); - - $array[$key] = trim($value); - } - $this->setResponseHeader($array); - } - - - /** - * @param $path - * @param $data - * @return string - */ - private function setParams($path, $data): string - { - if ($this->isGet()) { - if (!empty($data)) $path .= '?' . $data; - } else { - $data = $this->mergeParams($data); - if (!empty($data)) { - $this->withBody(new Stream($data)); - } - } - return $path; - } - - - /** - * - */ - public function close(): void - { - $this->client->close(); - } -} +withMethod($method) + ->coroutine( + $this->matchHost($path), + $this->paramEncode($params) + ); + } + + + /** + * @param $path + * @return $this + */ + public function withCAInfo($path): static + { + return $this; + } + + /** + * @param $url + * @param array|string $data + * @throws Exception 使用swoole协程方式请求 + */ + private function coroutine($url, array|string $data = []): void + { + try { + $this->generate_client($data, ...$url); + } catch (\Throwable $exception) { + Kiri::getDi()->get(Logger::class)->error('rpc', [$exception]); + $this->setStatusCode(-1); + $this->setBody(jTraceEx($exception)); + } + } + + + /** + * @param $data + * @param $host + * @param $isHttps + * @param $path + * @throws Exception + */ + private function generate_client($data, $host, $isHttps, $path): void + { + $this->client = new SwowClient(SWOOLE_TCP, FALSE); + if (!$this->client->connect($host, $this->getPort())) { + throw new Exception('链接失败'); + } + if ($isHttps || $this->isSSL()) { + $this->client->enableSSL(); + } + $this->client->set(array_merge($this->settings(), ['open_http_protocol' => true])); + if (!empty($this->getAgent())) { + $this->withAddedHeader('User-Agent', $this->getAgent()); + } + + $path = $this->setParams($path, $data); + + $this->withAddedHeader('Accept', ' text/html,application/xhtml+xml,application/json,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'); +// $this->withAddedHeader('Accept-Encoding', 'gzip'); + $this->withAddedHeader('Content-Length', $this->getData()->getSize()); + + $this->execute($path, $this->getData()->getContents()); + } + + + /** + * @param string $path + * @param string $content + * @return void + */ + private function execute(string $path, string $content) + { + $array = []; + $array[] = strtoupper($this->getMethod()) . ' ' . $path . ' HTTP/1.1'; + if (!empty($this->getHeader())) { + foreach ($this->getHeader() as $key => $value) { + $array[] = sprintf('%s: %s', $key, $value); + } + } + $this->client->send(implode("\r\n", $array) . "\r\n\r\n" . $content); + $receive = $this->client->recv(); + + [$header, $body] = explode("\r\n\r\n", $receive); + + $header = explode("\r\n", $header); + $status = array_shift($header); + + $this->setStatusCode(intval(explode(' ', $status)[1])); + $this->parseResponseHeaders($header); + $this->setBody($body); + } + + + private function chunked() + { + + } + + + /** + * @param array $headers + * @return void + */ + private function parseResponseHeaders(array $headers) + { + $array = []; + foreach ($headers as $header) { + [$key, $value] = explode(': ', $header); + + $array[$key] = trim($value); + } + $this->setResponseHeader($array); + } + + + /** + * @param $path + * @param $data + * @return string + */ + private function setParams($path, $data): string + { + if ($this->isGet()) { + if (!empty($data)) $path .= '?' . $data; + } else { + $data = $this->mergeParams($data); + if (!empty($data)) { + $this->withBody(new Stream($data)); + } + } + return $path; + } + + + /** + * + */ + public function close(): void + { + $this->client->close(); + } +} diff --git a/Client.php b/Client.php index 3295a99..b62b958 100644 --- a/Client.php +++ b/Client.php @@ -1,43 +1,43 @@ -abstracts = new CoroutineClient($host, $port, $isSsl); - } else { - $this->abstracts = new CurlClient($host, $port, $isSsl); - } - } - - - /** - * @param string $name - * @param array $arguments - * @return mixed - */ - public function __call(string $name, array $arguments) - { - return $this->abstracts->{$name}(...$arguments); - } - -} +abstracts = new CoroutineClient($host, $port, $isSsl); + } else { + $this->abstracts = new CurlClient($host, $port, $isSsl); + } + } + + + /** + * @param string $name + * @param array $arguments + * @return mixed + */ + public function __call(string $name, array $arguments) + { + return $this->abstracts->{$name}(...$arguments); + } + +} diff --git a/ClientAbstracts.php b/ClientAbstracts.php index 376787c..5d986b8 100644 --- a/ClientAbstracts.php +++ b/ClientAbstracts.php @@ -1,779 +1,779 @@ -VERIFYPEER = $bool; - return $this; - } - - - /** - * @return bool - */ - public function getVerifyPeer(): bool - { - return $this->VERIFYPEER; - } - - - /** - * @return int - */ - public function getStatusCode(): int - { - return $this->statusCode; - } - - - /** - * @return array - */ - public function getResponseHeaders(): array - { - return $this->_responseHeader; - } - - - /** - * @param string $key - * @return string|int|null - */ - public function getResponseHeader(string $key): null|string|int - { - return $this->_responseHeader[$key] ?? NULL; - } - - - /** - * @param array $responseHeader - */ - public function setResponseHeader(array $responseHeader): void - { - $this->_responseHeader = $responseHeader; - } - - - /** - * @param int $statusCode - */ - public function setStatusCode(int $statusCode): void - { - $this->statusCode = $statusCode; - } - - - /** - * @return string|null - */ - public function getBody(): string|null - { - return $this->body; - } - - - /** - * @param ?string $body - */ - public function setBody(?string $body): void - { - $this->body = $body; - } - - - /** - * @param $host - * @param $port - * @param false $isSSL - */ - public function __construct($host, $port, bool $isSSL = FALSE) - { - $this->withHost($host)->withPort($port)->withIsSSL($isSSL); - } - - - /** - * @param string $path - * @param array $params - */ - public function post(string $path, array $params = []): void - { - $this->request(self::POST, $path, $params); - } - - - /** - * @param string $path - * @param array $params - */ - public function put(string $path, array $params = []): void - { - $this->request(self::PUT, $path, $params); - } - - - /** - * @param string $contentType - * @return ClientAbstracts - */ - public function withContentType(string $contentType): static - { - $this->header['Content-Type'] = $contentType; - return $this; - } - - - /** - * @param string $path - * @param array $params - */ - public function head(string $path, array $params = []): void - { - $this->request(self::HEAD, $path, $params); - } - - - /** - * @param string $path - * @param array $params - */ - public function get(string $path, array $params = []): void - { - $this->request(self::GET, $path, $params); - } - - /** - * @param string $path - * @param array $params - */ - public function option(string $path, array $params = []): void - { - $this->request(self::OPTIONS, $path, $params); - } - - /** - * @param string $path - * @param array $params - */ - public function delete(string $path, array $params = []): void - { - $this->request(self::DELETE, $path, $params); - } - - /** - * @param string $path - * @param array $params - */ - public function options(string $path, array $params = []): void - { - $this->request(self::OPTIONS, $path, $params); - - } - - /** - * @param string $path - * @param array $params - */ - public function upload(string $path, array $params = []): void - { - $this->request(self::UPLOAD, $path, $params); - } - - - /** - * @return string - */ - public function getHost(): string - { - return $this->host; - } - - /** - * @return int - */ - #[Pure] protected function getHostPort(): int - { - if (!empty($this->getPort())) { - return $this->getPort(); - } - $port = 80; - if ($this->isSSL()) $port = 443; - return $port; - } - - - /** - * @param string $host - * @return ClientAbstracts - */ - private function withHost(string $host): static - { - $this->host = $host; - if (Context::inCoroutine()) { - $this->host = System::gethostbyname($host); - } - return $this->withAddedHeader('Host', $host); - } - - /** - * @return array - */ - public function getHeader(): array - { - return $this->header; - } - - - /** - * @return mixed|null - */ - public function getContentType(): ?string - { - return $this->header['Content-Type'] ?? $this->header['content-type'] ?? NULL; - } - - - /** - * @param array $header - * @return ClientAbstracts - */ - public function withHeader(array $header): static - { - $this->header = $header; - return $this; - } - - - /** - * @param array $header - * @return ClientAbstracts - */ - public function withHeaders(array $header): static - { - if (empty($header)) { - return $this; - } - foreach ($header as $key => $val) { - $this->header[$key] = $val; - } - return $this; - } - - /** - * @param $key - * @param $value - * @return ClientAbstracts - */ - public function withAddedHeader($key, $value): static - { - $this->header[$key] = $value; - return $this; - } - - /** - * @return int - */ - public function getTimeout(): int - { - return $this->timeout; - } - - /** - * @param int $value - * @return ClientAbstracts - */ - public function withTimeout(int $value): static - { - $this->timeout = $value; - return $this; - } - - - /** - * @param Closure|null $value - * @return ClientAbstracts - */ - public function withCallback(?Closure $value): static - { - return $this; - } - - /** - * @return string - */ - public function getMethod(): string - { - return $this->method; - } - - /** - * @param string $value - * @return static - */ - public function withMethod(string $value): static - { - $this->method = $value; - return $this; - } - - /** - * @return bool - */ - public function isSSL(): bool - { - return $this->isSSL; - } - - /** - * @param bool $isSSL - * @return ClientAbstracts - */ - public function withIsSSL(bool $isSSL): static - { - $this->isSSL = $isSSL; - return $this; - } - - /** - * @return string - */ - public function getAgent(): string - { - return $this->agent; - } - - /** - * @param string $agent - * @return ClientAbstracts - */ - public function withAgent(string $agent): static - { - $this->agent = $agent; - return $this; - } - - - /** - * @return string - */ - public function getSslCertFile(): string - { - return $this->ssl_cert_file; - } - - /** - * @param string $ssl_cert_file - * @return ClientAbstracts - */ - public function withSslCertFile(string $ssl_cert_file): static - { - $this->ssl_cert_file = $ssl_cert_file; - return $this; - } - - /** - * @return string - */ - public function getSslKeyFile(): string - { - return $this->ssl_key_file; - } - - /** - * @param string $ssl_key_file - * @return ClientAbstracts - */ - public function withSslKeyFile(string $ssl_key_file): static - { - $this->ssl_key_file = $ssl_key_file; - return $this; - } - - /** - * @return string - */ - public function getCa(): string - { - return $this->ca; - } - - /** - * @param string $ssl_key_file - * @return static - */ - public function withCa(string $ssl_key_file): static - { - $this->ca = $ssl_key_file; - return $this; - } - - /** - * @return int - */ - #[Pure] public function getPort(): int - { - if ($this->isSSL()) { - return 443; - } - if (empty($this->port)) { - return 80; - } - return $this->port; - } - - /** - * @param int $port - * @return ClientAbstracts - */ - private function withPort(int $port): static - { - $this->port = $port; - return $this; - } - - - /** - * @return StreamInterface - */ - public function getData(): StreamInterface - { - if (!$this->_data) { - $this->_data = new Stream(); - } - return $this->_data; - } - - /** - * @param string|StreamInterface $data - * @return ClientAbstracts - */ - public function withBody(string|StreamInterface $data): static - { - if (is_string($data)) { - $data = new Stream($data); - } - $this->_data = $data; - return $this; - } - - /** - * @return int - */ - public function getConnectTimeout(): int - { - return $this->connect_timeout; - } - - /** - * @param int $connect_timeout - * @return ClientAbstracts - */ - public function withConnectTimeout(int $connect_timeout): static - { - $this->connect_timeout = $connect_timeout; - return $this; - } - - - /** - * @param $host - * @return string|string[] - */ - protected function replaceHost($host): array|string - { - if ($this->isHttp($host)) { - return str_replace('http://', '', $host); - } - if ($this->isHttps($host)) { - return str_replace('https://', '', $host); - } - return $host; - } - - - /** - * @param $url - * @return false|int - */ - protected function checkIsIp($url): bool|int - { - return preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $url); - } - - /** - * @param $url - * @return bool - */ - protected function isHttp($url): bool - { - return str_starts_with($url, 'http://'); - } - - /** - * @param $url - * @return bool - */ - protected function isHttps($url): bool - { - return str_starts_with($url, 'https://'); - } - - - /** - * @param $newData - * @return string - */ - protected function mergeParams($newData): string - { - if (empty($data)) return ''; - if (!is_string($newData)) { - return $this->toRequest($newData); - } - return $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 - */ - 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 - { - return strtolower($this->method) === self::POST; - } - - /** - * @return bool - * check isPost Request - */ - #[Pure] protected function isUpload(): bool - { - return strtolower($this->method) === self::UPLOAD; - } - - - /** - * @return bool - * - * check isGet Request - */ - #[Pure] protected function isGet(): bool - { - return strtolower($this->method) === self::GET; - } - - /** - * @param $arr - * - * @return array|string - * 将请求参数进行编码 - */ - #[Pure] protected function paramEncode($arr): array|string - { - if (!is_array($arr)) { - return $arr; - } - $_tmp = []; - foreach ($arr as $Key => $val) { - $_tmp[$Key] = $val; - } - if ($this->isGet()) { - return http_build_query($_tmp); - } - return $_tmp; - } - - - /** - * @param string $string - * @return array - */ - protected function matchHost(string $string): array - { - if (($parse = isUrl($string, TRUE)) === FALSE) { - return $this->defaultString($string); - } - [$isHttps, $domain, $port, $path] = $parse; - if (str_contains($domain, ':' . $port)) { - $domain = str_replace(':' . $port, '', $domain); - } - $this->port = $isHttps ? 443 : $this->port; - if (isIp($domain)) { - $this->host = $domain; - } else if (Context::inCoroutine()) { - $this->host = System::gethostbyname($domain) ?? $domain; - } else { - $this->host = $domain; - } - $this->header['Host'] = $domain; - if (!str_starts_with($path, '/')) { - $path = '/' . $path; - } - return [$this->host, $isHttps, $path]; - } - - - /** - * @param $string - * @return array - */ - private function defaultString($string): array - { - $host = $this->getHost(); - if ($string == '/') { - $string = '/'; - } else if (!str_starts_with($string, '/')) { - $string = '/' . $string; - } - return [$host, $this->isSSL(), $string]; - } - - - /** - * @param $path - * @param $params - * @return string - */ - protected function joinGetParams($path, $params): string - { - if (empty($params)) { - return $path; - } - if (!is_string($params)) { - $params = http_build_query($params); - } - if (str_contains($path, '?')) { - [$path, $getParams] = explode('?', $path); - } - if (empty($getParams)) { - return $path . '?' . $params; - } - return $path . '?' . $params . '&' . $getParams; - } - -} +VERIFYPEER = $bool; + return $this; + } + + + /** + * @return bool + */ + public function getVerifyPeer(): bool + { + return $this->VERIFYPEER; + } + + + /** + * @return int + */ + public function getStatusCode(): int + { + return $this->statusCode; + } + + + /** + * @return array + */ + public function getResponseHeaders(): array + { + return $this->_responseHeader; + } + + + /** + * @param string $key + * @return string|int|null + */ + public function getResponseHeader(string $key): null|string|int + { + return $this->_responseHeader[$key] ?? NULL; + } + + + /** + * @param array $responseHeader + */ + public function setResponseHeader(array $responseHeader): void + { + $this->_responseHeader = $responseHeader; + } + + + /** + * @param int $statusCode + */ + public function setStatusCode(int $statusCode): void + { + $this->statusCode = $statusCode; + } + + + /** + * @return string|null + */ + public function getBody(): string|null + { + return $this->body; + } + + + /** + * @param ?string $body + */ + public function setBody(?string $body): void + { + $this->body = $body; + } + + + /** + * @param $host + * @param $port + * @param false $isSSL + */ + public function __construct($host, $port, bool $isSSL = FALSE) + { + $this->withHost($host)->withPort($port)->withIsSSL($isSSL); + } + + + /** + * @param string $path + * @param array $params + */ + public function post(string $path, array $params = []): void + { + $this->request(self::POST, $path, $params); + } + + + /** + * @param string $path + * @param array $params + */ + public function put(string $path, array $params = []): void + { + $this->request(self::PUT, $path, $params); + } + + + /** + * @param string $contentType + * @return ClientAbstracts + */ + public function withContentType(string $contentType): static + { + $this->header['Content-Type'] = $contentType; + return $this; + } + + + /** + * @param string $path + * @param array $params + */ + public function head(string $path, array $params = []): void + { + $this->request(self::HEAD, $path, $params); + } + + + /** + * @param string $path + * @param array $params + */ + public function get(string $path, array $params = []): void + { + $this->request(self::GET, $path, $params); + } + + /** + * @param string $path + * @param array $params + */ + public function option(string $path, array $params = []): void + { + $this->request(self::OPTIONS, $path, $params); + } + + /** + * @param string $path + * @param array $params + */ + public function delete(string $path, array $params = []): void + { + $this->request(self::DELETE, $path, $params); + } + + /** + * @param string $path + * @param array $params + */ + public function options(string $path, array $params = []): void + { + $this->request(self::OPTIONS, $path, $params); + + } + + /** + * @param string $path + * @param array $params + */ + public function upload(string $path, array $params = []): void + { + $this->request(self::UPLOAD, $path, $params); + } + + + /** + * @return string + */ + public function getHost(): string + { + return $this->host; + } + + /** + * @return int + */ + #[Pure] protected function getHostPort(): int + { + if (!empty($this->getPort())) { + return $this->getPort(); + } + $port = 80; + if ($this->isSSL()) $port = 443; + return $port; + } + + + /** + * @param string $host + * @return ClientAbstracts + */ + private function withHost(string $host): static + { + $this->host = $host; + if (Context::inCoroutine()) { + $this->host = System::gethostbyname($host); + } + return $this->withAddedHeader('Host', $host); + } + + /** + * @return array + */ + public function getHeader(): array + { + return $this->header; + } + + + /** + * @return mixed|null + */ + public function getContentType(): ?string + { + return $this->header['Content-Type'] ?? $this->header['content-type'] ?? NULL; + } + + + /** + * @param array $header + * @return ClientAbstracts + */ + public function withHeader(array $header): static + { + $this->header = $header; + return $this; + } + + + /** + * @param array $header + * @return ClientAbstracts + */ + public function withHeaders(array $header): static + { + if (empty($header)) { + return $this; + } + foreach ($header as $key => $val) { + $this->header[$key] = $val; + } + return $this; + } + + /** + * @param $key + * @param $value + * @return ClientAbstracts + */ + public function withAddedHeader($key, $value): static + { + $this->header[$key] = $value; + return $this; + } + + /** + * @return int + */ + public function getTimeout(): int + { + return $this->timeout; + } + + /** + * @param int $value + * @return ClientAbstracts + */ + public function withTimeout(int $value): static + { + $this->timeout = $value; + return $this; + } + + + /** + * @param Closure|null $value + * @return ClientAbstracts + */ + public function withCallback(?Closure $value): static + { + return $this; + } + + /** + * @return string + */ + public function getMethod(): string + { + return $this->method; + } + + /** + * @param string $value + * @return static + */ + public function withMethod(string $value): static + { + $this->method = $value; + return $this; + } + + /** + * @return bool + */ + public function isSSL(): bool + { + return $this->isSSL; + } + + /** + * @param bool $isSSL + * @return ClientAbstracts + */ + public function withIsSSL(bool $isSSL): static + { + $this->isSSL = $isSSL; + return $this; + } + + /** + * @return string + */ + public function getAgent(): string + { + return $this->agent; + } + + /** + * @param string $agent + * @return ClientAbstracts + */ + public function withAgent(string $agent): static + { + $this->agent = $agent; + return $this; + } + + + /** + * @return string + */ + public function getSslCertFile(): string + { + return $this->ssl_cert_file; + } + + /** + * @param string $ssl_cert_file + * @return ClientAbstracts + */ + public function withSslCertFile(string $ssl_cert_file): static + { + $this->ssl_cert_file = $ssl_cert_file; + return $this; + } + + /** + * @return string + */ + public function getSslKeyFile(): string + { + return $this->ssl_key_file; + } + + /** + * @param string $ssl_key_file + * @return ClientAbstracts + */ + public function withSslKeyFile(string $ssl_key_file): static + { + $this->ssl_key_file = $ssl_key_file; + return $this; + } + + /** + * @return string + */ + public function getCa(): string + { + return $this->ca; + } + + /** + * @param string $ssl_key_file + * @return static + */ + public function withCa(string $ssl_key_file): static + { + $this->ca = $ssl_key_file; + return $this; + } + + /** + * @return int + */ + #[Pure] public function getPort(): int + { + if ($this->isSSL()) { + return 443; + } + if (empty($this->port)) { + return 80; + } + return $this->port; + } + + /** + * @param int $port + * @return ClientAbstracts + */ + private function withPort(int $port): static + { + $this->port = $port; + return $this; + } + + + /** + * @return StreamInterface + */ + public function getData(): StreamInterface + { + if (!$this->_data) { + $this->_data = new Stream(); + } + return $this->_data; + } + + /** + * @param string|StreamInterface $data + * @return ClientAbstracts + */ + public function withBody(string|StreamInterface $data): static + { + if (is_string($data)) { + $data = new Stream($data); + } + $this->_data = $data; + return $this; + } + + /** + * @return int + */ + public function getConnectTimeout(): int + { + return $this->connect_timeout; + } + + /** + * @param int $connect_timeout + * @return ClientAbstracts + */ + public function withConnectTimeout(int $connect_timeout): static + { + $this->connect_timeout = $connect_timeout; + return $this; + } + + + /** + * @param $host + * @return string|string[] + */ + protected function replaceHost($host): array|string + { + if ($this->isHttp($host)) { + return str_replace('http://', '', $host); + } + if ($this->isHttps($host)) { + return str_replace('https://', '', $host); + } + return $host; + } + + + /** + * @param $url + * @return false|int + */ + protected function checkIsIp($url): bool|int + { + return preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $url); + } + + /** + * @param $url + * @return bool + */ + protected function isHttp($url): bool + { + return str_starts_with($url, 'http://'); + } + + /** + * @param $url + * @return bool + */ + protected function isHttps($url): bool + { + return str_starts_with($url, 'https://'); + } + + + /** + * @param $newData + * @return string + */ + protected function mergeParams($newData): string + { + if (empty($data)) return ''; + if (!is_string($newData)) { + return $this->toRequest($newData); + } + return $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 + */ + 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 + { + return strtolower($this->method) === self::POST; + } + + /** + * @return bool + * check isPost Request + */ + #[Pure] protected function isUpload(): bool + { + return strtolower($this->method) === self::UPLOAD; + } + + + /** + * @return bool + * + * check isGet Request + */ + #[Pure] protected function isGet(): bool + { + return strtolower($this->method) === self::GET; + } + + /** + * @param $arr + * + * @return array|string + * 将请求参数进行编码 + */ + #[Pure] protected function paramEncode($arr): array|string + { + if (!is_array($arr)) { + return $arr; + } + $_tmp = []; + foreach ($arr as $Key => $val) { + $_tmp[$Key] = $val; + } + if ($this->isGet()) { + return http_build_query($_tmp); + } + return $_tmp; + } + + + /** + * @param string $string + * @return array + */ + protected function matchHost(string $string): array + { + if (($parse = isUrl($string, TRUE)) === FALSE) { + return $this->defaultString($string); + } + [$isHttps, $domain, $port, $path] = $parse; + if (str_contains($domain, ':' . $port)) { + $domain = str_replace(':' . $port, '', $domain); + } + $this->port = $isHttps ? 443 : $this->port; + if (isIp($domain)) { + $this->host = $domain; + } else if (Context::inCoroutine()) { + $this->host = System::gethostbyname($domain) ?? $domain; + } else { + $this->host = $domain; + } + $this->header['Host'] = $domain; + if (!str_starts_with($path, '/')) { + $path = '/' . $path; + } + return [$this->host, $isHttps, $path]; + } + + + /** + * @param $string + * @return array + */ + private function defaultString($string): array + { + $host = $this->getHost(); + if ($string == '/') { + $string = '/'; + } else if (!str_starts_with($string, '/')) { + $string = '/' . $string; + } + return [$host, $this->isSSL(), $string]; + } + + + /** + * @param $path + * @param $params + * @return string + */ + protected function joinGetParams($path, $params): string + { + if (empty($params)) { + return $path; + } + if (!is_string($params)) { + $params = http_build_query($params); + } + if (str_contains($path, '?')) { + [$path, $getParams] = explode('?', $path); + } + if (empty($getParams)) { + return $path . '?' . $params; + } + return $path . '?' . $params . '&' . $getParams; + } + +} diff --git a/CoroutineClient.php b/CoroutineClient.php index b013fb6..a8269da 100644 --- a/CoroutineClient.php +++ b/CoroutineClient.php @@ -1,129 +1,129 @@ -withMethod($method) - ->coroutine( - $this->matchHost($path), - $this->paramEncode($params) - ); - } - - - - /** - * @param $path - * @return $this - */ - public function withCAInfo($path): static - { - return $this; - } - - /** - * @param $url - * @param array|string $data - * @throws Exception 使用swoole协程方式请求 - */ - private function coroutine($url, array|string $data = []): void - { - try { - $this->generate_client($data, ...$url); - if ($this->client->statusCode < 0) { - throw new Exception($this->client->errMsg); - } - $this->setStatusCode($this->client->getStatusCode()); - $this->setBody($this->client->getBody()); - $this->setResponseHeader($this->client->headers); - } catch (\Throwable $exception) { - Kiri::getDi()->get(Logger::class)->error('rpc', [$exception]); - $this->setStatusCode(-1); - $this->setBody(jTraceEx($exception)); - } - } - - - /** - * @param $data - * @param $host - * @param $isHttps - * @param $path - */ - private function generate_client($data, $host, $isHttps, $path): void - { - if ($isHttps || $this->isSSL()) { - $this->client = new SwowClient($host, 443, true); - } else { - $this->client = new SwowClient($host, $this->getPort(), false); - } - $this->client->set($this->settings()); - if (!empty($this->getAgent())) { - $this->withAddedHeader('User-Agent', $this->getAgent()); - } - $this->client->setHeaders($this->getHeader()); - $this->client->setMethod(strtoupper($this->getMethod())); - $this->client->execute($this->setParams($path, $data)); - } - - - /** - * @param $path - * @param $data - * @return string - */ - private function setParams($path, $data): string - { - $content = $this->getData()->getContents(); - if (!empty($content)) { - $this->client->setData($content); - } - if ($this->isGet()) { - if (!empty($data)) $path .= '?' . $data; - } else { - $data = $this->mergeParams($data); - if (!empty($data)) { - $this->client->setData($data); - } - } - return $path; - } - - /** - * - */ - public function close(): void - { - $this->client->close(); - } -} +withMethod($method) + ->coroutine( + $this->matchHost($path), + $this->paramEncode($params) + ); + } + + + + /** + * @param $path + * @return $this + */ + public function withCAInfo($path): static + { + return $this; + } + + /** + * @param $url + * @param array|string $data + * @throws Exception 使用swoole协程方式请求 + */ + private function coroutine($url, array|string $data = []): void + { + try { + $this->generate_client($data, ...$url); + if ($this->client->statusCode < 0) { + throw new Exception($this->client->errMsg); + } + $this->setStatusCode($this->client->getStatusCode()); + $this->setBody($this->client->getBody()); + $this->setResponseHeader($this->client->headers); + } catch (\Throwable $exception) { + Kiri::getDi()->get(Logger::class)->error('rpc', [$exception]); + $this->setStatusCode(-1); + $this->setBody(jTraceEx($exception)); + } + } + + + /** + * @param $data + * @param $host + * @param $isHttps + * @param $path + */ + private function generate_client($data, $host, $isHttps, $path): void + { + if ($isHttps || $this->isSSL()) { + $this->client = new SwowClient($host, 443, true); + } else { + $this->client = new SwowClient($host, $this->getPort(), false); + } + $this->client->set($this->settings()); + if (!empty($this->getAgent())) { + $this->withAddedHeader('User-Agent', $this->getAgent()); + } + $this->client->setHeaders($this->getHeader()); + $this->client->setMethod(strtoupper($this->getMethod())); + $this->client->execute($this->setParams($path, $data)); + } + + + /** + * @param $path + * @param $data + * @return string + */ + private function setParams($path, $data): string + { + $content = $this->getData()->getContents(); + if (!empty($content)) { + $this->client->setData($content); + } + if ($this->isGet()) { + if (!empty($data)) $path .= '?' . $data; + } else { + $data = $this->mergeParams($data); + if (!empty($data)) { + $this->client->setData($data); + } + } + return $path; + } + + /** + * + */ + public function close(): void + { + $this->client->close(); + } +} diff --git a/CurlClient.php b/CurlClient.php index 12dd994..c851a9a 100644 --- a/CurlClient.php +++ b/CurlClient.php @@ -1,208 +1,208 @@ -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, $isHttps, $path] = $this->matchHost($path); - - $host = $isHttps ? 'https://' . $host : 'http://' . $host; - if ($this->getPort() != 443 && $this->getPort() != 80) { - $host .= ':' . $this->getPort(); - } - $this->do(curl_init($host . $path), $host . $path, $method); - if ($isHttps !== FALSE) { - $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->setStatusCode(curl_errno($this->client)); - $this->setBody(curl_error($this->client)); - } else { - $this->explode($output); - } - } - - - /** - * - */ - 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)); - - $this->setStatusCode(intval($status[1])); - $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 - */ - #[Pure] private function parseHeaderMat(): array - { - $headers = []; - foreach ($this->getHeader() as $key => $val) { - $headers[$key] = $key . ': ' . $val; - } - return array_values($headers); - } -} +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, $isHttps, $path] = $this->matchHost($path); + + $host = $isHttps ? 'https://' . $host : 'http://' . $host; + if ($this->getPort() != 443 && $this->getPort() != 80) { + $host .= ':' . $this->getPort(); + } + $this->do(curl_init($host . $path), $host . $path, $method); + if ($isHttps !== FALSE) { + $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->setStatusCode(curl_errno($this->client)); + $this->setBody(curl_error($this->client)); + } else { + $this->explode($output); + } + } + + + /** + * + */ + 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)); + + $this->setStatusCode(intval($status[1])); + $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 + */ + #[Pure] private function parseHeaderMat(): array + { + $headers = []; + foreach ($this->getHeader() as $key => $val) { + $headers[$key] = $key . ': ' . $val; + } + return array_values($headers); + } +} diff --git a/HttpParse.php b/HttpParse.php index ba46c2f..b415485 100644 --- a/HttpParse.php +++ b/HttpParse.php @@ -1,109 +1,109 @@ - $value) { - if ($value === null) { - continue; - } - if (is_array($value)) { - $value = key($value); - } - if ($first === '') { - $first = $value; - } else { - $tp[] = $value; - } - } - $key = $first . '[' . implode('][', $tp) . ']'; - if (count($tp) < 1) { - $key = $first; - } - return $key; - } - - /** - * @param $data - * @return string - * @throws Exception - */ - public static function parse($data): string - { - $tmp = []; - if (is_string($data)) { - return $data; - } - foreach ($data as $key => $datum) { - if ($datum === null) { - continue; - } - $tmp[] = static::ifElse($key, $datum); - } - return implode('&', $tmp); - } - - /** - * @param $t - * @param $qt - * @return string - * @throws Exception - */ - private static function ifElse($t, $qt): string - { - if (is_numeric($qt)) { - return $t . '=' . $qt; - } - if (is_string($qt)) { - $string = $t . '=' . urlencode($qt); - } else { - $string = static::encode($t, $qt); - } - return $string; - } - - /** - * @param mixed ...$object - * @return string - * @throws Exception - */ - private static function encode(...$object): string - { - $ret = []; - - $data = $object[count($object) - 1]; - $key = static::getKey(...$object); - foreach ($data as $s => $datum) { - if (is_array($datum)) { - $object[count($object) - 1] = $s; - $object[] = $datum; - $string = static::encode(...$object); - } else { - if (is_object($datum)) { - throw new Exception('Http body con\'t object.'); - } - $string = $key . '=' . urlencode($datum); - } - $ret[] = $string; - } - return implode('&', $ret); - } - - -} + $value) { + if ($value === null) { + continue; + } + if (is_array($value)) { + $value = key($value); + } + if ($first === '') { + $first = $value; + } else { + $tp[] = $value; + } + } + $key = $first . '[' . implode('][', $tp) . ']'; + if (count($tp) < 1) { + $key = $first; + } + return $key; + } + + /** + * @param $data + * @return string + * @throws Exception + */ + public static function parse($data): string + { + $tmp = []; + if (is_string($data)) { + return $data; + } + foreach ($data as $key => $datum) { + if ($datum === null) { + continue; + } + $tmp[] = static::ifElse($key, $datum); + } + return implode('&', $tmp); + } + + /** + * @param $t + * @param $qt + * @return string + * @throws Exception + */ + private static function ifElse($t, $qt): string + { + if (is_numeric($qt)) { + return $t . '=' . $qt; + } + if (is_string($qt)) { + $string = $t . '=' . urlencode($qt); + } else { + $string = static::encode($t, $qt); + } + return $string; + } + + /** + * @param mixed ...$object + * @return string + * @throws Exception + */ + private static function encode(...$object): string + { + $ret = []; + + $data = $object[count($object) - 1]; + $key = static::getKey(...$object); + foreach ($data as $s => $datum) { + if (is_array($datum)) { + $object[count($object) - 1] = $s; + $object[] = $datum; + $string = static::encode(...$object); + } else { + if (is_object($datum)) { + throw new Exception('Http body con\'t object.'); + } + $string = $key . '=' . urlencode($datum); + } + $ret[] = $string; + } + return implode('&', $ret); + } + + +} diff --git a/IClient.php b/IClient.php index 43478f9..1962f00 100644 --- a/IClient.php +++ b/IClient.php @@ -1,181 +1,181 @@ -getSslCertFile(); - $sslKey = $this->getSslKeyFile(); - $sslCa = $this->getCa(); - - $params = []; - if ($this->getConnectTimeout() > 0) { - $params['timeout'] = $this->getConnectTimeout(); - } - if (empty($sslCert) || empty($sslKey) || empty($sslCa)) { - return $params; - } - - $params['ssl_host_name'] = $this->getHost(); - $params['ssl_cert_file'] = $this->getSslCertFile(); - $params['ssl_key_file'] = $this->getSslKeyFile(); - $params['ssl_verify_peer'] = TRUE; - $params['ssl_cafile'] = $sslCa; - - return $params; - } - +getSslCertFile(); + $sslKey = $this->getSslKeyFile(); + $sslCa = $this->getCa(); + + $params = []; + if ($this->getConnectTimeout() > 0) { + $params['timeout'] = $this->getConnectTimeout(); + } + if (empty($sslCert) || empty($sslKey) || empty($sslCa)) { + return $params; + } + + $params['ssl_host_name'] = $this->getHost(); + $params['ssl_cert_file'] = $this->getSslCertFile(); + $params['ssl_key_file'] = $this->getSslKeyFile(); + $params['ssl_verify_peer'] = TRUE; + $params['ssl_cafile'] = $sslCa; + + return $params; + } + } \ No newline at end of file diff --git a/composer.json b/composer.json index c538f6c..615289f 100644 --- a/composer.json +++ b/composer.json @@ -1,25 +1,25 @@ -{ - "name": "game-worker/kiri-client", - "description": "db", - "authors": [ - { - "name": "XiangLin", - "email": "as2252258@163.com" - } - ], - "license": "MIT", - "require": { - "php": ">=8.0", - "ext-json": "*", - "ext-swoole": "*", - "psr/http-client": "^1.0", - "psr/http-message": "^1.0" - }, - "autoload": { - "psr-4": { - "Http\\Client\\": "./" - } - }, - "require-dev": { - } -} +{ + "name": "game-worker/kiri-client", + "description": "db", + "authors": [ + { + "name": "XiangLin", + "email": "as2252258@163.com" + } + ], + "license": "MIT", + "require": { + "php": ">=8.0", + "ext-json": "*", + "ext-swoole": "*", + "psr/http-client": "^1.0", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Http\\Client\\": "./" + } + }, + "require-dev": { + } +}