diff --git a/README.md b/README.md index e753e06..e89cdcb 100644 --- a/README.md +++ b/README.md @@ -6,20 +6,20 @@ PHP http client library. -- driver contains: `curl` `swoole` -- implement the [PSR 18](https://github.com/php-fig/http-client) +- 可用的驱动包括: `curl` `swoole` `fsockopen` +- 实现接口 [PSR 18](https://github.com/php-fig/http-client) -## Install +## 安装 ```bash composer require php-comp/http-client ``` -## Usage +## 使用 ### CURL -- simple +- 简单使用 ```php use PhpComp\Http\Client\Curl\Curl; @@ -40,7 +40,7 @@ $curl->reset()->post('/users/1', $post); $array = $curl->getArrayData(); ``` -- file upload/download +- 文件上传下载 ```text public function upload(string $url, string $field, string $filePath, string $mimeType = '') diff --git a/src/AbstractClient.php b/src/AbstractClient.php index e0b0da3..538f4e5 100644 --- a/src/AbstractClient.php +++ b/src/AbstractClient.php @@ -120,9 +120,9 @@ abstract class AbstractClient implements ClientInterface protected $error = ''; /** - * @var int response status code + * @var int response status code. eg. 200 404 */ - protected $statusCode = 200; + protected $statusCode = 0; /** * @var string body string, it's parsed from $_response @@ -179,6 +179,21 @@ public static function getSupportedMethods() return self::$supportedMethods; } + /** + * @param string $method + * @return string + */ + protected function formatAndCheckMethod(string $method): string + { + $method = \strtoupper($method); + + if (!isset(self::$supportedMethods[$method])) { + throw new \InvalidArgumentException("The method type [$method] is not supported!"); + } + + return $method; + } + /************************************************************************** * request methods *************************************************************************/ @@ -262,7 +277,7 @@ public function sendRequest(RequestInterface $request): ResponseInterface } // send request - $this->request($request->getRequestTarget(), $request->getBody(), $request->getMethod()); + $this->request($request->getRequestTarget(), (string)$request->getBody(), $request->getMethod()); return $this->getPsr7Response(); } @@ -437,8 +452,10 @@ public function addHeaders(array $headers, bool $override = true) */ public function setHeader(string $name, string $value, bool $override = false) { + $name = \ucwords($name); + if ($override || !isset($this->headers[$name])) { - $this->headers[$name] = \ucwords($name) . ": $value"; + $this->headers[$name] = $value; } return $this; @@ -679,7 +696,6 @@ public function isDebug(): bool public function setDebug($debug) { $this->options['debug'] = (bool)$debug; - return $this; } @@ -701,6 +717,48 @@ public function __toString(): string return $this->getResponseBody(); } + /** + * @return bool|array + */ + public function getArrayData() + { + return $this->getJsonArray(); + } + + /** + * @return bool|array + */ + public function getJsonArray() + { + if (!$body = $this->getResponseBody()) { + return []; + } + + $data = \json_decode($body, true); + if (\json_last_error() > 0) { + return false; + } + + return $data; + } + + /** + * @return bool|\stdClass + */ + public function getJsonObject() + { + if (!$body = $this->getResponseBody()) { + return false; + } + + $data = \json_decode($body); + if (\json_last_error() > 0) { + return false; + } + + return $data; + } + /** * @return string */ diff --git a/src/ClientUtil.php b/src/ClientUtil.php index 9bda20b..45bf4c0 100644 --- a/src/ClientUtil.php +++ b/src/ClientUtil.php @@ -8,6 +8,8 @@ namespace PhpComp\Http\Client; +use PhpComp\Http\Client\Error\ClientException; + /** * Class ClientUtil * @package PhpComp\Http\Client @@ -36,6 +38,20 @@ public static function mergeArray(array $src, array $append): array return $src; } + /** + * @param array $arr + * @return array + */ + public static function ucwordArrayKeys(array $arr): array + { + $newMap = []; + foreach ($arr as $key => $value) { + $newMap[\ucwords($key)] = $value; + } + + return $newMap; + } + /** * @param string $url * @return bool @@ -45,6 +61,28 @@ public static function isFullURL(string $url): bool return 0 === \strpos($url, 'http:') || 0 === \strpos($url, 'https:') || 0 === strpos($url, '//'); } + /** + * @param string $url + * @return array + */ + public static function parseUrl(string $url): array + { + $info = \parse_url($url); + if ($info === false) { + throw new ClientException('invalid request url: ' . $url); + } + + $info = \array_merge([ + 'scheme' => 'http', + 'host' => '', + 'port' => 80, + 'path' => '/', + 'query' => '', + ], $info); + + return $info; + } + /** * @param string $url * @param array|object $data diff --git a/src/Curl/Curl.php b/src/Curl/Curl.php index c042556..14e5296 100644 --- a/src/Curl/Curl.php +++ b/src/Curl/Curl.php @@ -10,6 +10,7 @@ use PhpComp\Http\Client\AbstractClient; use PhpComp\Http\Client\ClientUtil; +use PhpComp\Http\Client\RawResponseParserTrait; /** * Class Curl @@ -34,6 +35,8 @@ */ class Curl extends AbstractClient implements CurlClientInterface { + use RawResponseParserTrait; + // ssl auth type const SSL_TYPE_CERT = 'cert'; const SSL_TYPE_KEY = 'key'; @@ -86,17 +89,6 @@ class Curl extends AbstractClient implements CurlClientInterface //CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' ]; - /************************************************************************** - * response data. - *************************************************************************/ - - /** - * The curl exec response data string. contains headers and body - * @var string - */ - private $_response; - private $_responseParsed = false; - /** * save request and response info, data from curl_getinfo() * @link https://secure.php.net/manual/zh/function.curl-getinfo.php @@ -256,10 +248,6 @@ public function request(string $url, $data = null, string $method = 'GET', array $options['method'] = $method; } - if (!isset(self::$supportedMethods[$method])) { - throw new \InvalidArgumentException("The method type [$method] is not supported!"); - } - $url = $this->buildUrl($url); $ch = $this->prepareRequest($url, $data, $headers, $options); @@ -284,8 +272,17 @@ public function request(string $url, $data = null, string $method = 'GET', array break; } + // if \CURLOPT_HEADER is FALSE, only return body. no headers data + if (false === $this->getCurlOption(\CURLOPT_HEADER, false)) { + $this->responseBody = $response; + $this->responseParsed = true; + } else { + // if CURLOPT_HEADER is TRUE, The raw response data contains headers and body + $this->rawResponse = $response; + $this->parseResponse(); // parse raw response data + } + $this->_responseInfo = \curl_getinfo($ch); - $this->_response = $response; $this->statusCode = (int)$this->_responseInfo['http_code']; // close resource @@ -308,9 +305,6 @@ protected function prepareRequest(string $url, $data, array $headers, array $opt { $this->resetResponse(); - // init curl - $ch = \curl_init(); - // open debug if ($this->isDebug()) { $this->_curlOptions[\CURLOPT_VERBOSE] = true; @@ -323,7 +317,7 @@ protected function prepareRequest(string $url, $data, array $headers, array $opt // merge global options. $options = \array_merge($this->options, $options); - $method = $options['method']; + $method = $this->formatAndCheckMethod($options['method']); switch ($method) { case 'GET': @@ -343,6 +337,9 @@ protected function prepareRequest(string $url, $data, array $headers, array $opt $curlOptions[\CURLOPT_CUSTOMREQUEST] = $method; } + // init curl + $ch = \curl_init(); + // add send data if ($data) { // allow post data @@ -389,58 +386,6 @@ protected function prepareRequest(string $url, $data, array $headers, array $opt return $ch; } - /** - * parse response data string. - */ - public function parseResponse() - { - // have been parsed || no response data - if ($this->_responseParsed || !($response = $this->_response)) { - return ; - } - - // if only return body. no return headers data - if (false === $this->getCurlOption(\CURLOPT_HEADER, false)) { - $this->responseBody = $response; - $this->_responseParsed = true; - return; - } - - # Headers regex - $pattern = '#HTTP/\d\.\d.*?$.*?\r\n\r\n#ims'; - - # Extract headers from response - \preg_match_all($pattern, $response, $matches); - $headers_string = array_pop($matches[0]); - $headers = \explode("\r\n", str_replace("\r\n\r\n", '', $headers_string)); - - # Include all received headers in the $headers_string - while (\count($matches[0])) { - $headers_string = \array_pop($matches[0]) . $headers_string; - } - - # Remove all headers from the response body - $this->responseBody = \str_replace($headers_string, '', $response); - - # Extract the version and status from the first header - $versionAndStatus = \array_shift($headers); - - \preg_match_all('#HTTP/(\d\.\d)\s((\d\d\d)\s((.*?)(?=HTTP)|.*))#', $versionAndStatus, $matches); - - // '1.1' 200 '200 OK' - $this->responseHeaders['Http-Version'] = \array_pop($matches[1]); - $this->responseHeaders['Status-Code'] = \array_pop($matches[3]); - $this->responseHeaders['Status'] = \array_pop($matches[2]); - - # Convert headers into an associative array - foreach ($headers as $header) { - \preg_match('#(.*?)\:\s(.*)#', $header, $matches); - $this->responseHeaders[$matches[1]] = $matches[2]; - } - - $this->_responseParsed = true; - } - /////////////////////////////////////////////////////////////////////// // response data /////////////////////////////////////////////////////////////////////// @@ -461,66 +406,6 @@ public function getTotalTime(): int return $this->_responseInfo['total_time'] ?? 0; } - /** - * @return string - */ - public function getResponse() - { - return $this->_response; - } - - /** - * @return string - */ - public function getResponseBody() - { - $this->parseResponse(); - - return $this->responseBody; - } - - /** - * @return bool|array - */ - public function getArrayData() - { - return $this->getJsonArray(); - } - - /** - * @return bool|array - */ - public function getJsonArray() - { - if (!$this->getResponseBody()) { - return []; - } - - $data = \json_decode($this->responseBody, true); - if (\json_last_error() > 0) { - return false; - } - - return $data; - } - - /** - * @return bool|\stdClass - */ - public function getJsonObject() - { - if (!$this->getResponseBody()) { - return false; - } - - $data = \json_decode($this->responseBody); - if (\json_last_error() > 0) { - return false; - } - - return $data; - } - /** * @return $this */ @@ -537,8 +422,8 @@ public function resetOptions() */ public function resetResponse() { - $this->_response = ''; - $this->_responseParsed = false; + $this->rawResponse = ''; + $this->responseParsed = false; parent::resetResponse(); return $this; diff --git a/src/FSockClient.php b/src/FSockClient.php index dfe72cc..04cd023 100644 --- a/src/FSockClient.php +++ b/src/FSockClient.php @@ -8,25 +8,150 @@ namespace PhpComp\Http\Client; -use Psr\Http\Client\ClientInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - /** * Class FSocketOpen client * @package PhpComp\Http\Client */ -class FSockClient implements ClientInterface +class FSockClient extends AbstractClient { + use RawResponseParserTrait; + + /** + * @return bool + */ + public static function isAvailable(): bool + { + return \function_exists('fsockopen'); + } + /** - * Sends a PSR-7 request and returns a PSR-7 response. - * - * @param RequestInterface $request - * @return ResponseInterface - * @throws \Psr\Http\Client\ClientExceptionInterface If an error happens while processing the request. + * Send request to remote URL + * @param $url + * @param array $data + * @param string $method + * @param array $headers + * @param array $options + * @return self */ - public function sendRequest(RequestInterface $request): ResponseInterface + public function request(string $url, $data = null, string $method = self::GET, array $headers = [], array $options = []) + { + if ($method) { + $options['method'] = \strtoupper($method); + } + + // get request url info + $info = ClientUtil::parseUrl($this->buildUrl($url)); + $timeout = $this->getTimeout(); + + // open sock + $fp = \fsockopen($info['host'], $info['port'], $errno, $error, $timeout); + + // save error info + if (!$fp) { + $this->errNo = $errno; + $this->error = $error; + return $this; + } + + // set timeout + \stream_set_timeout($fp, $timeout); + + $string = $this->buildHttpData($info, $headers, $options, $data); + \fwrite($fp, $string); // send request + + // read response + while (!\feof($fp)) { + $this->rawResponse .= \fread($fp, 4096); + } + + \fclose($fp); + + // parse raw response + $this->parseResponse(); + + return $this; + } + + protected function buildHttpData(array $info, array $headers, array $opts, $data) { - // TODO: Implement sendRequest() method. + $uri = $info['path']; + if ($info['query']) { + $uri .= '?' . $info['query']; + } + + // merge global options data. + $opts = \array_merge($this->options, $opts); + + // build cookies value + if ($cookies = \array_merge($this->cookies, $opts['cookies'])) { + // "Cookie: name=value; name1=value1" + $headers['Cookie'] = \http_build_query($cookies, '', '; '); + } + + $headers = \array_merge($this->headers, $opts['headers'], $headers); + $headers = ClientUtil::ucwordArrayKeys($headers); + + if (!isset($headers['Host'])) { + $headers['Host'] = $info['host']; + } + + $method = $this->formatAndCheckMethod($opts['method']); + + // $heads[] = "Host: www.example.com\r\n"; + // $heads[] = "Connection: Close\r\n"; + + $body = ''; + if ($data) { + // allow submit body + if ($method === 'POST' || $method === 'PUT' || $method === 'PATCH') { + $body = $this->buildBodyByContentType($headers, $data); + } else { + $uri = ClientUtil::buildURL($uri, $data); + } + } + + // close connection. if not add, will blocked. + if (!isset($headers['Connection'])) { + $headers['Connection'] = 'close'; + } + + $fmtHeaders = $this->formatHeaders($headers); + + // eg. "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n" + return \sprintf( + "%s %s HTTP/1.1\r\n%s\r\n\r\n%s", + $method, $uri, \implode("\r\n", $fmtHeaders), $body + ); + } + + private function buildBodyByContentType(array &$headers, $data): string + { + $defContentType = 'application/x-www-form-urlencoded'; + + if (\is_scalar($data)) { + if (!isset($headers['Content-Type'])) { + $headers['Content-Type'] = $defContentType; + } + + return (string)$data; + } + + // data is array or object. + if (isset($headers['Content-Type'])) { + $ct = $headers['Content-Type']; + + // application/x-www-form-urlencoded + if (\stripos($ct, 'x-www-form-urlencoded')) { + return \http_build_query($data); + } + + if (\stripos($ct, 'json')) { + return (string)\json_encode($data); + } + } else { + $headers['Content-Type'] = $defContentType; + } + + return \http_build_query($data); } } diff --git a/src/RawResponseParserTrait.php b/src/RawResponseParserTrait.php new file mode 100644 index 0000000..9e11dc1 --- /dev/null +++ b/src/RawResponseParserTrait.php @@ -0,0 +1,84 @@ +responseParsed || '' === $this->rawResponse) { + return; + } + + $response = $this->rawResponse; + + # Headers regex + $pattern = '#HTTP/\d\.\d.*?$.*?\r\n\r\n#ims'; + + # Extract headers from response + \preg_match_all($pattern, $response, $matches); + $headers_string = array_pop($matches[0]); + $headers = \explode("\r\n", str_replace("\r\n\r\n", '', $headers_string)); + + # Include all received headers in the $headers_string + while (\count($matches[0])) { + $headers_string = \array_pop($matches[0]) . $headers_string; + } + + # Remove all headers from the response body + $this->responseBody = \str_replace($headers_string, '', $response); + + # Extract the version and status from the first header + $versionAndStatus = \array_shift($headers); + + \preg_match_all('#HTTP/(\d\.\d)\s((\d\d\d)\s((.*?)(?=HTTP)|.*))#', $versionAndStatus, $matches); + + // '1.1' 200 '200 OK' + $this->responseHeaders['Http-Version'] = \array_pop($matches[1]); + + $statusCode = \array_pop($matches[3]); + if ($this->statusCode === 0) { + $this->statusCode = $statusCode; + } + + $this->responseHeaders['Status-Msg'] = \array_pop($matches[2]); + + # Convert headers into an associative array + foreach ($headers as $header) { + \preg_match('#(.*?)\:\s(.*)#', $header, $matches); + $this->responseHeaders[$matches[1]] = $matches[2]; + } + + $this->rawResponse = ''; + $this->responseParsed = true; + } + + /** + * @param string $rawResponse + */ + public function setRawResponse(string $rawResponse) + { + $this->rawResponse = $rawResponse; + } +} \ No newline at end of file diff --git a/src/StreamClient.php b/src/StreamClient.php index 6c0d150..72105fd 100644 --- a/src/StreamClient.php +++ b/src/StreamClient.php @@ -8,25 +8,31 @@ namespace PhpComp\Http\Client; -use Psr\Http\Client\ClientInterface; -use Psr\Http\Message\RequestInterface; -use Psr\Http\Message\ResponseInterface; - /** * Class StreamClient * @package PhpComp\Http\Client */ -class StreamClient implements ClientInterface +class StreamClient extends AbstractClient { /** - * Sends a PSR-7 request and returns a PSR-7 response. - * - * @param RequestInterface $request - * @return ResponseInterface - * @throws \Psr\Http\Client\ClientExceptionInterface If an error happens while processing the request. + * @return bool + */ + public static function isAvailable(): bool + { + // TODO: Implement isAvailable() method. + } + + /** + * Send request to remote URL + * @param $url + * @param array $data + * @param string $method + * @param array $headers + * @param array $options + * @return self */ - public function sendRequest(RequestInterface $request): ResponseInterface + public function request(string $url, $data = null, string $method = self::GET, array $headers = [], array $options = []) { - // TODO: Implement sendRequest() method. + // TODO: Implement request() method. } } diff --git a/src/Swoole/CoClient.php b/src/Swoole/CoClient.php index bf28119..b54875b 100644 --- a/src/Swoole/CoClient.php +++ b/src/Swoole/CoClient.php @@ -9,7 +9,7 @@ namespace PhpComp\Http\Client\Swoole; use PhpComp\Http\Client\AbstractClient; -use PhpComp\Http\Client\Error\ClientException; +use PhpComp\Http\Client\ClientUtil; use Swoole\Coroutine\Http\Client; /** @@ -24,6 +24,11 @@ class CoClient extends AbstractClient */ private $client; + /** + * @var bool + */ + private $defer = false; + /** * @return bool */ @@ -32,6 +37,29 @@ public static function isAvailable(): bool return \class_exists(Client::class); } + /** + * File download and save + * @param string $url + * @param string $saveAs + * @return bool + * @throws \Exception + */ + public function download(string $url, string $saveAs): bool + { + // get request url info + $info = ClientUtil::parseUrl($this->buildUrl($url)); + + $uri = $info['path']; + if ($info['query']) { + $uri .= '?' . $info['query']; + } + + $client = $this->newSwooleClient($info); + $this->prepareClient($client, [], []); + + return $client->download($uri, $saveAs); + } + /** * Send request to remote URL * @param $url @@ -43,17 +71,18 @@ public static function isAvailable(): bool */ public function request(string $url, $data = null, string $method = self::GET, array $headers = [], array $options = []) { + if ($method) { + $options['method'] = \strtoupper($method); + } + // get request url info - $info = $this->parseUrl($this->buildUrl($url)); + $info = ClientUtil::parseUrl($this->buildUrl($url)); // create co client - $client = $this->makeSwooleClient($info); - - $method = \strtoupper($method); - $client->setMethod($method); + $client = $this->newSwooleClient($info); // prepare client - $this->prepareClient($client, [], []); + $this->prepareClient($client, $headers, $options); // add data if ($data) { @@ -68,45 +97,32 @@ public function request(string $url, $data = null, string $method = self::GET, a // do send request. $client->execute($uri); - // check error - if ($this->errNo = $client->errCode) { - $this->error = \socket_strerror($client->errCode); - } else { - $this->responseBody = $client->body; - $this->responseHeaders = $client->headers; - $this->statusCode = $client->statusCode; + // not use defer. + if (!$this->defer) { + $this->collectResponse($client); + $client->close(); } - $client->close(); $this->client = $client; - return $this; } /** - * File download and save - * @param string $url - * @param string $saveAs - * @return bool - * @throws \Exception + * only available on defer is true + * @return $this */ - public function download(string $url, string $saveAs): bool + public function receive() { - // get request url info - $info = $this->parseUrl($this->buildUrl($url)); - - $uri = $info['path']; - if ($info['query']) { - $uri .= '?' . $info['query']; + if ($this->defer && $this->client !== null) { + // receive response + $this->client->recv($this->getTimeout()); + $this->collectResponse($this->client); } - $client = $this->makeSwooleClient($info); - $this->prepareClient($client, [], []); - - return $client->download($uri, $saveAs); + return $this; } - private function makeSwooleClient(array $info): Client + private function newSwooleClient(array $info): Client { // enable SSL verify // options: 'sslVerify' => false/true, @@ -131,6 +147,10 @@ private function prepareClient(Client $client, array $headers, array $options) // merge global options data. $options = \array_merge($this->options, $options); + // set method + $method = $this->formatAndCheckMethod($options['method']); + $client->setMethod($method); + // set headers if ($headers = \array_merge($this->headers, $options['headers'], $headers)) { $client->setHeaders($headers); @@ -140,24 +160,23 @@ private function prepareClient(Client $client, array $headers, array $options) if ($cookies = \array_merge($this->cookies, $options['cookies'])) { $client->setCookies($cookies); } + + // open defer + if ($this->defer) { + $client->setDefer(true); + } } - protected function parseUrl(string $url): array + private function collectResponse(Client $client) { - $info = \parse_url($url); - if ($info === false) { - throw new ClientException('invalid request url'); + // check error + if ($this->errNo = $client->errCode) { + $this->error = \socket_strerror($client->errCode); + } else { + $this->responseBody = $client->body; + $this->responseHeaders = $client->headers; + $this->statusCode = $client->statusCode; } - - $info = \array_merge([ - 'scheme' => 'http', - 'host' => '', - 'port' => 80, - 'path' => '/', - 'query' => '', - ], $info); - - return $info; } /** @@ -167,4 +186,22 @@ public function getClient(): Client { return $this->client; } + + /** + * @return bool + */ + public function isDefer(): bool + { + return $this->defer; + } + + /** + * @param bool $defer + * @return CoClient + */ + public function setDefer(bool $defer = true) + { + $this->defer = $defer; + return $this; + } } diff --git a/src/Swoole/CoClient2.php b/src/Swoole/CoClient2.php index 06fb767..0603fdc 100644 --- a/src/Swoole/CoClient2.php +++ b/src/Swoole/CoClient2.php @@ -9,7 +9,9 @@ namespace PhpComp\Http\Client\Swoole; use PhpComp\Http\Client\AbstractClient; +use PhpComp\Http\Client\ClientUtil; use Swoole\Coroutine\Http2\Client; +use Swoole\Coroutine\Http2\Request; /** * Class CoClient2 - http2 client @@ -18,6 +20,11 @@ */ class CoClient2 extends AbstractClient { + /** + * @var Client + */ + private $client; + /** * @return bool */ @@ -37,6 +44,76 @@ public static function isAvailable(): bool */ public function request(string $url, $data = null, string $method = self::GET, array $headers = [], array $options = []) { + if ($method) { + $options['method'] = \strtoupper($method); + } + + // get request url info + $info = ClientUtil::parseUrl($this->buildUrl($url)); + + // enable SSL verify + // options: 'sslVerify' => false/true, + $sslVerify = (bool)$this->getOption('sslVerify'); + + if ($info['scheme'] === 'https' || $info['scheme'] === 'wss') { + $sslVerify = true; + } + + $client = new Client($info['host'], $info['port'], $sslVerify); + // some client option + $client->set([ + // 'timeout' => -1 + 'timeout' => $this->getTimeout(), + 'ssl_host_name' => $info['host'] + ]); + $client->connect(); + + $uri = $info['path']; + if ($info['query']) { + $uri .= '?' . $info['query']; + } + + $req = new Request(); + $req->path = $uri; + $this->prepareRequest($req, $headers, $options); + + if ($data) { + $req->data = $data; + } + + // send request + $client->send($req); + $resp = $client->recv(); + $this->responseBody = $resp->data; + $client->close(); + return $this; } + + private function prepareRequest(Request $request, array $headers, array $options) + { + // merge global options data. + $options = \array_merge($this->options, $options); + + // set method + $request->method = $this->formatAndCheckMethod($options['method']); + + // set headers + if ($headers = \array_merge($this->headers, $options['headers'], $headers)) { + $request->headers = $headers; + } + + // set cookies + if ($cookies = \array_merge($this->cookies, $options['cookies'])) { + $request->cookies = $cookies; + } + } + + /** + * @return Client + */ + public function getClient(): Client + { + return $this->client; + } } diff --git a/test/CurlClientTest.php b/test/CurlClientTest.php index 4104567..d37778d 100644 --- a/test/CurlClientTest.php +++ b/test/CurlClientTest.php @@ -31,7 +31,6 @@ public function testBasic() $this->assertEquals(0, $c->getErrNo()); $this->assertEquals('', $c->getError()); $this->assertEquals(200, $c->getStatusCode()); - $this->assertNotEmpty($c->getResponse()); $this->assertNotEmpty($c->getBody()); $this->assertNotEmpty($c->getResponseHeaders()); @@ -51,7 +50,7 @@ public function testDownload() { $c = Curl::create(); $url = 'https://github.com/php-comp/http-client/archive/master.zip'; - $file = __DIR__.'/down-test.zip'; + $file = __DIR__ . '/down-test.zip'; $ok = $c->download($url, $file); $this->assertTrue($ok); diff --git a/test/FSockClientTest.php b/test/FSockClientTest.php new file mode 100644 index 0000000..c0e076d --- /dev/null +++ b/test/FSockClientTest.php @@ -0,0 +1,29 @@ +get('http://www.baidu.com'); + + $this->assertFalse($c->hasError()); + $this->assertEquals(200, $c->getStatusCode()); + } +} diff --git a/test/Swoole/CoClientTest.php b/test/Swoole/CoClientTest.php index 90510ad..4ad7602 100644 --- a/test/Swoole/CoClientTest.php +++ b/test/Swoole/CoClientTest.php @@ -10,7 +10,7 @@ use PhpComp\Http\Client\Swoole\CoClient; use PHPUnit\Framework\TestCase; -use Swoole\Runtime; +use Swoole\Timer; /** * Class CoClientTest @@ -19,25 +19,59 @@ */ class CoClientTest extends TestCase { - /* - protected function setUp() - { - Runtime::enableCoroutine(true); - } - protected function tearDown() { - Runtime::enableCoroutine(false); - }*/ + // parent::tearDown(); + Timer::after(3 * 1000, function () { + \swoole_event_exit(); + }); + } public function testGet() { - \go(function () { + if (!CoClient::isAvailable()) { + return; + } + + // http + $cid = \go(function () { $c = CoClient::create(); $c->get('http://www.baidu.com'); + $this->assertFalse($c->isDefer()); $this->assertFalse($c->hasError()); + $this->assertNotEmpty($c->getBody()); + $this->assertNotEmpty($c->getResponseHeaders()); + // \swoole_event_exit(); + }); + + $this->assertTrue($cid > 0); + } + + public function testDefer() + { + if (!CoClient::isAvailable()) { + return; + } + + $cid = \go(function () { + $c = CoClient::create(); + $c->setDefer()->get('http://www.baidu.com'); + + $this->assertTrue($c->isDefer()); + $this->assertFalse($c->hasError()); + $this->assertEmpty($c->getBody()); + $this->assertEmpty($c->getResponseHeaders()); + + $c->receive(); + + $this->assertFalse($c->hasError()); + $this->assertNotEmpty($c->getBody()); + $this->assertNotEmpty($c->getResponseHeaders()); + + // \swoole_event_exit(); }); + $this->assertTrue($cid > 0); } } diff --git a/test/boot.php b/test/boot.php index 6b027e1..7a33d76 100644 --- a/test/boot.php +++ b/test/boot.php @@ -30,6 +30,7 @@ require $file; } -function my_include_file($file) { +function my_include_file($file) +{ include $file; }