Framework Update
This commit is contained in:
Vendored
+77
-3
@@ -13,6 +13,11 @@ gitee:[gitee.com/yzh52521/easyhttp](https://gitee.com/yzh52521/easyhttp "gitee.c
|
||||
1. 增加 retry() 重试机制。
|
||||
2. 增加 debug 日志调试功能。
|
||||
3. 增加 withHost 指定服务端base_url
|
||||
4. 增加 withBody 发送原始数据(Raw)请求
|
||||
5. 增加 withMiddleware/withRequestMiddleware/withResponseMiddleware Guzzle 中间件
|
||||
6. 增加 connectTimeout 设置等待服务器响应超时
|
||||
7. 增加 sink 响应的主体部分将要保存的位置
|
||||
8. 增加 maxRedirects 请求的重定向行为最大次数
|
||||
|
||||
|
||||
# 安装说明
|
||||
@@ -53,6 +58,7 @@ $response = Http::delete(...);
|
||||
$response = Http::head(...);
|
||||
|
||||
$response = Http::options(...);
|
||||
|
||||
```
|
||||
|
||||
###### 指定服务端base_url的请求
|
||||
@@ -61,6 +67,12 @@ $response = Http::options(...);
|
||||
// 指定服务端base_url地址,最终请求地址为 https://serv.yzh52521.com/login
|
||||
$response = Http::withHost('https://serv.yzh52521.com')->post('/login');
|
||||
|
||||
```
|
||||
##### 发送原始数据(Raw)请求
|
||||
```php
|
||||
$response = Http::withBody(
|
||||
base64_encode($photo), 'image/jpeg'
|
||||
)->post(...);
|
||||
```
|
||||
###### 发送 Content-Type 编码请求
|
||||
|
||||
@@ -114,8 +126,12 @@ $response = Http::withRedirect([
|
||||
'protocols' => ['http', 'https'],
|
||||
'track_redirects' => false
|
||||
])->post(...);
|
||||
|
||||
$response = Http::maxRedirects(5)->post(...);
|
||||
```
|
||||
|
||||
|
||||
|
||||
###### 携带认证的请求
|
||||
|
||||
```php
|
||||
@@ -182,6 +198,12 @@ $response = Http::withProxy([
|
||||
$response = Http::timeout(60)->post(...);
|
||||
```
|
||||
|
||||
###### 设置等待服务器响应超时的最大值(单位秒)
|
||||
|
||||
```php
|
||||
$response = Http::connectTimeout(60)->post(...);
|
||||
```
|
||||
|
||||
###### 设置延迟时间(单位秒)
|
||||
|
||||
```php
|
||||
@@ -199,6 +221,42 @@ $response = Http::concurrency(10)->promise(...);
|
||||
```php
|
||||
$response = Http::retry(3, 100)->post(...);
|
||||
```
|
||||
##### 响应的主体部分将要保存的位置
|
||||
```php
|
||||
$response = Http::sink('/path/to/file')->post(...);
|
||||
```
|
||||
|
||||
#### Guzzle 中间件
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Middleware;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
$response = Http::withMiddleware(
|
||||
Middleware::mapRequest(function (RequestInterface $request) {
|
||||
$request = $request->withHeader('X-Example', 'Value');
|
||||
return $request;
|
||||
})
|
||||
)->get('http://example.com');
|
||||
|
||||
………………
|
||||
$response = Http::withRequestMiddleware(
|
||||
function (RequestInterface $request) {
|
||||
$request = $request->withHeader('X-Example', 'Value');
|
||||
return $request;
|
||||
}
|
||||
)->get('http://example.com');
|
||||
|
||||
………………
|
||||
|
||||
$response = Http::withResponseMiddleware(
|
||||
function (RequestInterface $response) {
|
||||
$response = $response->getHeader('X-Example');
|
||||
return $response;
|
||||
}
|
||||
)->get('http://example.com');
|
||||
```
|
||||
|
||||
#### 异步请求
|
||||
|
||||
@@ -206,22 +264,26 @@ $response = Http::retry(3, 100)->post(...);
|
||||
use yzh52521\EasyHttp\Response;
|
||||
use yzh52521\EasyHttp\RequestException;
|
||||
|
||||
Http::getAsync('http://easyhttp.yzh52521.cn/api/sleep3.json', ['token' => TOKEN], function (Response $response) {
|
||||
$promise = Http::getAsync('http://easyhttp.yzh52521.cn/api/sleep3.json', ['token' => TOKEN], function (Response $response) {
|
||||
echo '异步请求成功,响应内容:' . $response->body() . PHP_EOL;
|
||||
}, function (RequestException $e) {
|
||||
echo '异步请求异常,错误码:' . $e->getCode() . ',错误信息:' . $e->getMessage() . PHP_EOL;
|
||||
});
|
||||
|
||||
$promise->wait();
|
||||
echo json_encode(['code' => 200, 'msg' => '请求成功'], JSON_UNESCAPED_UNICODE) . PHP_EOL;
|
||||
|
||||
//输出
|
||||
{"code":200,"msg":"请求成功"}
|
||||
异步请求成功,响应内容:{"code":200,"msg":"success","second":3}
|
||||
|
||||
Http::getAsync('http1://easyhttp.yzh52521.cn/api/sleep3.json', function (Response $response) {
|
||||
$promise = Http::getAsync('http1://easyhttp.yzh52521.cn/api/sleep3.json', function (Response $response) {
|
||||
echo '异步请求成功,响应内容:' . $response->body() . PHP_EOL;
|
||||
}, function (RequestException $e) {
|
||||
echo '异步请求异常,错误信息:' . $e->getMessage() . PHP_EOL;
|
||||
});
|
||||
|
||||
$promise->wait();
|
||||
echo json_encode(['code' => 200, 'msg' => '请求成功'], JSON_UNESCAPED_UNICODE) . PHP_EOL;
|
||||
|
||||
//输出
|
||||
@@ -239,6 +301,9 @@ Http::deleteAsync(...);
|
||||
Http::headAsync(...);
|
||||
|
||||
Http::optionsAsync(...);
|
||||
|
||||
使用 等待异步回调处理完成
|
||||
Http::wait();
|
||||
```
|
||||
|
||||
#### 异步并发请求
|
||||
@@ -253,12 +318,15 @@ $promises = [
|
||||
Http::postAsync('http://easyhttp.yzh52521.cn/api/sleep2.json', ['name' => 'yzh52521']),
|
||||
];
|
||||
|
||||
Http::concurrency(10)->multiAsync($promises, function (Response $response, $index) {
|
||||
$pool=Http::concurrency(10)->multiAsync($promises, function (Response $response, $index) {
|
||||
echo "发起第 $index 个异步请求,请求时长:" . $response->json()->second . '秒' . PHP_EOL;
|
||||
}, function (RequestException $e, $index) {
|
||||
echo "发起第 $index 个请求失败,失败原因:" . $e->getMessage() . PHP_EOL;
|
||||
});
|
||||
|
||||
$promise = $pool->promise();
|
||||
$promise->wait();
|
||||
|
||||
//输出
|
||||
发起第 1 个请求失败,失败原因:cURL error 1: Protocol "http1" not supported or disabled in libcurl (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)
|
||||
发起第 2 个异步请求,请求时长:2 秒
|
||||
@@ -306,6 +374,12 @@ Http::debug(Log::class)->post(...);
|
||||
|
||||
|
||||
## 更新日志
|
||||
### 2023-08-31
|
||||
* 新增 withBody 可以发送原始数据(Raw)请求
|
||||
* 新增 withMiddleware/withRequestMiddleware/withResponseMiddleware 支持Guzzle中间件
|
||||
* 新增 connectTimeout 设置等待服务器响应超时
|
||||
* 新增 sink 响应的主体部分将要保存的位置
|
||||
* 新增 maxRedirects 请求的重定向行为最大次数
|
||||
### 2022-05-11
|
||||
* 新增removeBodyFormat() 用于withOptions 指定body时,清除原由的bodyFromat
|
||||
### 2022-05-10
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.2.5|^8.0",
|
||||
"php": ">=7.2.5",
|
||||
"guzzlehttp/guzzle": "^6.0|^7.0",
|
||||
"psr/log":"^1.0|^2.0|^3.0"
|
||||
},
|
||||
|
||||
+7
-2
@@ -11,11 +11,16 @@ class Facade
|
||||
$this->facade = new $this->facade;
|
||||
}
|
||||
|
||||
public function __call($name, $params) {
|
||||
public function __call($name, $params)
|
||||
{
|
||||
if (method_exists($this->facade, 'removeOptions')) {
|
||||
call_user_func_array([$this->facade, 'removeOptions'], []);
|
||||
}
|
||||
return call_user_func_array([$this->facade, $name], $params);
|
||||
}
|
||||
|
||||
public static function __callStatic($name, $params) {
|
||||
public static function __callStatic($name, $params)
|
||||
{
|
||||
return call_user_func_array([new static(), $name], $params);
|
||||
}
|
||||
}
|
||||
|
||||
+27
-19
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace yzh52521\EasyHttp;
|
||||
|
||||
|
||||
/**
|
||||
* @method static \yzh52521\EasyHttp\Request asJson()
|
||||
* @method static \yzh52521\EasyHttp\Request asForm()
|
||||
@@ -13,6 +14,7 @@ namespace yzh52521\EasyHttp;
|
||||
* @method static \yzh52521\EasyHttp\Request withVerify(bool|string $verify)
|
||||
* @method static \yzh52521\EasyHttp\Request withHost(string $host)
|
||||
* @method static \yzh52521\EasyHttp\Request withHeaders(array $headers)
|
||||
* @method static \yzh52521\EasyHttp\Request withBody($content,$contentType='application/json')
|
||||
* @method static \yzh52521\EasyHttp\Request withBasicAuth(string $username, string $password)
|
||||
* @method static \yzh52521\EasyHttp\Request withDigestAuth(string $username, string $password)
|
||||
* @method static \yzh52521\EasyHttp\Request withUA(string $ua)
|
||||
@@ -21,33 +23,39 @@ namespace yzh52521\EasyHttp;
|
||||
* @method static \yzh52521\EasyHttp\Request withProxy(string|array $proxy)
|
||||
* @method static \yzh52521\EasyHttp\Request withVersion(string $version)
|
||||
* @method static \yzh52521\EasyHttp\Request withOptions(array $options)
|
||||
* @method static \yzh52521\EasyHttp\Request withMiddleware(callable $middleware)
|
||||
* @method static \yzh52521\EasyHttp\Request withRequestMiddleware(callable $middleware)
|
||||
* @method static \yzh52521\EasyHttp\Request withResponseMiddleware(callable $middleware)
|
||||
*
|
||||
* @method static \yzh52521\EasyHttp\Request debug($class)
|
||||
* @method static \yzh52521\EasyHttp\Request retry(int $retries=1,int $sleep=0)
|
||||
* @method static \yzh52521\EasyHttp\Request delay(int $seconds)
|
||||
* @method static \yzh52521\EasyHttp\Request timeout(int $seconds)
|
||||
* @method static \yzh52521\EasyHttp\Request timeout(float $seconds)
|
||||
* @method static \yzh52521\EasyHttp\Request connectTimeout(float $seconds)
|
||||
* @method static \yzh52521\EasyHttp\Request sink(string|resource $to)
|
||||
* @method static \yzh52521\EasyHttp\Request concurrency(int $times)
|
||||
* @method static \yzh52521\EasyHttp\Request client(string $method, string $url, array $options = [])
|
||||
* @method static \yzh52521\EasyHttp\Request clientAsync(string $method, string $url, array $options = [])
|
||||
* @method static \yzh52521\EasyHttp\Request removeBodyFormat()
|
||||
* @method static \yzh52521\EasyHttp\Request maxRedirects(int $max)
|
||||
*
|
||||
* @method static \yzh52521\EasyHttp\Request get(string $url, array $query = [])
|
||||
* @method static \yzh52521\EasyHttp\Request post(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Request patch(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Request put(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Request delete(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Request head(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Request options(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Response get(string $url, array $query = [])
|
||||
* @method static \yzh52521\EasyHttp\Response post(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Response patch(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Response put(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Response delete(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Response head(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Response options(string $url, array $data = [])
|
||||
* @method static \yzh52521\EasyHttp\Response client(string $method, string $url, array $options = [])
|
||||
* @method static \yzh52521\EasyHttp\Response clientAsync(string $method, string $url, array $options = [])
|
||||
*
|
||||
* @method static \yzh52521\EasyHttp\Request getAsync(string $url, array|null $query = null, callable $success = null, callable $fail = null)
|
||||
* @method static \yzh52521\EasyHttp\Request postAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \yzh52521\EasyHttp\Request patchAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \yzh52521\EasyHttp\Request putAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \yzh52521\EasyHttp\Request deleteAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \yzh52521\EasyHttp\Request headAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \yzh52521\EasyHttp\Request optionsAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \yzh52521\EasyHttp\Request multiAsync(array $promises, callable $success = null, callable $fail = null)
|
||||
* @method static \yzh52521\EasyHttp\Request wait()
|
||||
* @method static \GuzzleHttp\Promise\PromiseInterface getAsync(string $url, array|null $query = null, callable $success = null, callable $fail = null)
|
||||
* @method static \GuzzleHttp\Promise\PromiseInterface postAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \GuzzleHttp\Promise\PromiseInterface patchAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \GuzzleHttp\Promise\PromiseInterface putAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \GuzzleHttp\Promise\PromiseInterface deleteAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \GuzzleHttp\Promise\PromiseInterface headAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \GuzzleHttp\Promise\PromiseInterface optionsAsync(string $url, array|null $data = null, callable $success = null, callable $fail = null)
|
||||
* @method static \GuzzleHttp\Pool multiAsync(array $promises, callable $success = null, callable $fail = null)
|
||||
* @method static void wait()
|
||||
*/
|
||||
|
||||
class Http extends Facade
|
||||
|
||||
+242
-146
@@ -5,6 +5,7 @@ namespace yzh52521\EasyHttp;
|
||||
use GuzzleHttp\Handler\CurlHandler;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
|
||||
use GuzzleHttp\Middleware;
|
||||
use GuzzleHttp\Pool;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Promise;
|
||||
@@ -16,7 +17,7 @@ use GuzzleHttp\Exception\ConnectException;
|
||||
* @method \yzh52521\EasyHttp\Response array()
|
||||
* @method \yzh52521\EasyHttp\Response json()
|
||||
* @method \yzh52521\EasyHttp\Response headers()
|
||||
* @method \yzh52521\EasyHttp\Response header( string $header )
|
||||
* @method \yzh52521\EasyHttp\Response header(string $header)
|
||||
* @method \yzh52521\EasyHttp\Response status()
|
||||
* @method \yzh52521\EasyHttp\Response successful()
|
||||
* @method \yzh52521\EasyHttp\Response ok()
|
||||
@@ -44,6 +45,13 @@ class Request
|
||||
*/
|
||||
protected $bodyFormat;
|
||||
|
||||
/**
|
||||
* The raw body for the request.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $pendingBody;
|
||||
|
||||
protected $isRemoveBodyFormat = false;
|
||||
|
||||
/**
|
||||
@@ -76,14 +84,11 @@ class Request
|
||||
{
|
||||
$this->client = $this->getInstance();
|
||||
|
||||
$this->bodyFormat = 'form_params';
|
||||
$this->options = [
|
||||
$this->bodyFormat = 'form_params';
|
||||
$this->options = [
|
||||
'http_errors' => false,
|
||||
];
|
||||
if (!$this->handlerStack instanceof HandlerStack) {
|
||||
$this->handlerStack = HandlerStack::create( new CurlHandler() );
|
||||
}
|
||||
$this->options['handler'] = $this->handlerStack;
|
||||
$this->handlerStack = HandlerStack::create(new CurlHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,9 +96,7 @@ class Request
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (!empty( $this->promises )) {
|
||||
Promise\settle( $this->promises )->wait();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,17 +107,28 @@ class Request
|
||||
{
|
||||
$name = get_called_class();
|
||||
|
||||
if (!isset( self::$instances[$name] )) {
|
||||
if (!isset(self::$instances[$name])) {
|
||||
self::$instances[$name] = new Client();
|
||||
}
|
||||
|
||||
return self::$instances[$name];
|
||||
}
|
||||
|
||||
public function removeOptions()
|
||||
{
|
||||
$this->bodyFormat = 'form_params';
|
||||
$this->isRemoveBodyFormat = false;
|
||||
$this->options = [
|
||||
'http_errors' => false,
|
||||
'verify' => false
|
||||
];
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function asForm()
|
||||
{
|
||||
$this->bodyFormat = 'form_params';
|
||||
$this->withHeaders( ['Content-Type' => 'application/x-www-form-urlencoded'] );
|
||||
$this->withHeaders(['Content-Type' => 'application/x-www-form-urlencoded']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -122,21 +136,48 @@ class Request
|
||||
public function asJson()
|
||||
{
|
||||
$this->bodyFormat = 'json';
|
||||
$this->withHeaders( ['Content-Type' => 'application/json'] );
|
||||
$this->withHeaders(['Content-Type' => 'application/json']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function asMultipart(string $name,string $contents,string $filename = null,array $headers = [])
|
||||
public function asMultipart(string $name, string $contents, string $filename = null, array $headers = [])
|
||||
{
|
||||
$this->bodyFormat = 'multipart';
|
||||
|
||||
$this->options = array_filter( [
|
||||
$this->options = array_filter([
|
||||
'name' => $name,
|
||||
'contents' => $contents,
|
||||
'headers' => $headers,
|
||||
'filename' => $filename,
|
||||
] );
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withMiddleware(callable $middleware)
|
||||
{
|
||||
$this->handlerStack->push($middleware);
|
||||
|
||||
$this->options['handler'] = $this->handlerStack;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withRequestMiddleware(callable $middleware)
|
||||
{
|
||||
$this->handlerStack->push(Middleware::mapRequest($middleware));
|
||||
|
||||
$this->options['handler'] = $this->handlerStack;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withResponseMiddleware(callable $middleware)
|
||||
{
|
||||
$this->handlerStack->push(Middleware::mapResponse($middleware));
|
||||
|
||||
$this->options['handler'] = $this->handlerStack;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -150,62 +191,73 @@ class Request
|
||||
|
||||
public function withOptions(array $options)
|
||||
{
|
||||
unset( $this->options[$this->bodyFormat],$this->options['body'] );
|
||||
unset($this->options[$this->bodyFormat], $this->options['body']);
|
||||
|
||||
$this->options = array_merge_recursive( $this->options,$options );
|
||||
$this->options = array_merge_recursive($this->options, $options);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withCert(string $path,string $password)
|
||||
public function withCert(string $path, string $password)
|
||||
{
|
||||
$this->options['cert'] = [$path,$password];
|
||||
$this->options['cert'] = [$path, $password];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withHeaders(array $headers)
|
||||
{
|
||||
$this->options = array_merge_recursive( $this->options,[
|
||||
$this->options = array_merge_recursive($this->options, [
|
||||
'headers' => $headers,
|
||||
] );
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withBasicAuth(string $username,string $password)
|
||||
public function withBody($content, $contentType = 'application/json')
|
||||
{
|
||||
$this->options['auth'] = [$username,$password];
|
||||
$this->bodyFormat = 'body';
|
||||
|
||||
$this->options['headers']['Content-Type'] = $contentType;
|
||||
|
||||
$this->pendingBody = $content;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withDigestAuth(string $username,string $password)
|
||||
public function withBasicAuth(string $username, string $password)
|
||||
{
|
||||
$this->options['auth'] = [$username,$password,'digest'];
|
||||
$this->options['auth'] = [$username, $password];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withDigestAuth(string $username, string $password)
|
||||
{
|
||||
$this->options['auth'] = [$username, $password, 'digest'];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withUA(string $ua)
|
||||
{
|
||||
$this->options['headers']['User-Agent'] = trim( $ua );
|
||||
$this->options['headers']['User-Agent'] = trim($ua);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withToken(string $token,string $type = 'Bearer')
|
||||
public function withToken(string $token, string $type = 'Bearer')
|
||||
{
|
||||
$this->options['headers']['Authorization'] = trim( $type.' '.$token );
|
||||
$this->options['headers']['Authorization'] = trim($type . ' ' . $token);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withCookies(array $cookies,string $domain)
|
||||
public function withCookies(array $cookies, string $domain)
|
||||
{
|
||||
$this->options = array_merge_recursive( $this->options,[
|
||||
'cookies' => CookieJar::fromArray( $cookies,$domain ),
|
||||
] );
|
||||
$this->options = array_merge_recursive($this->options, [
|
||||
'cookies' => CookieJar::fromArray($cookies, $domain),
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -224,6 +276,13 @@ class Request
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function maxRedirects(int $max)
|
||||
{
|
||||
$this->options['allow_redirects']['max'] = $max;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withRedirect($redirect = false)
|
||||
{
|
||||
$this->options['allow_redirects'] = $redirect;
|
||||
@@ -252,9 +311,10 @@ class Request
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function retry(int $retries = 1,int $sleep = 0)
|
||||
public function retry(int $retries = 1, int $sleep = 0)
|
||||
{
|
||||
$this->handlerStack->push( ( new Retry() )->handle( $retries,$sleep ) );
|
||||
$this->handlerStack->push((new Retry())->handle($retries, $sleep));
|
||||
|
||||
$this->options['handler'] = $this->handlerStack;
|
||||
|
||||
return $this;
|
||||
@@ -267,9 +327,27 @@ class Request
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function timeout(int $seconds)
|
||||
public function timeout(float $seconds)
|
||||
{
|
||||
$this->options['timeout'] = $seconds * 1000;
|
||||
$this->options['timeout'] = $seconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function connectTimeout(float $seconds)
|
||||
{
|
||||
$this->options['connect_timeout'] = $seconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|resource $to
|
||||
* @return $this
|
||||
*/
|
||||
public function sink($to)
|
||||
{
|
||||
$this->options['sink'] = $to;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -282,17 +360,17 @@ class Request
|
||||
|
||||
public function debug($class)
|
||||
{
|
||||
$logger = new Logger( function ($level,$message,array $context) use ($class) {
|
||||
$class::log( $level,$message );
|
||||
},function ($request,$response,$reason) {
|
||||
$logger = new Logger(function ($level, $message, array $context) use ($class) {
|
||||
$class::log($level, $message);
|
||||
}, function ($request, $response, $reason) {
|
||||
$requestBody = $request->getBody();
|
||||
$requestBody->rewind();
|
||||
|
||||
//请求头
|
||||
$requestHeaders = [];
|
||||
|
||||
foreach ( (array)$request->getHeaders() as $k => $vs ) {
|
||||
foreach ( $vs as $v ) {
|
||||
foreach ((array)$request->getHeaders() as $k => $vs) {
|
||||
foreach ($vs as $v) {
|
||||
$requestHeaders[] = "$k: $v";
|
||||
}
|
||||
}
|
||||
@@ -300,8 +378,8 @@ class Request
|
||||
//响应头
|
||||
$responseHeaders = [];
|
||||
|
||||
foreach ( (array)$response->getHeaders() as $k => $vs ) {
|
||||
foreach ( $vs as $v ) {
|
||||
foreach ((array)$response->getHeaders() as $k => $vs) {
|
||||
foreach ($vs as $v) {
|
||||
$responseHeaders[] = "$k: $v";
|
||||
}
|
||||
}
|
||||
@@ -310,7 +388,7 @@ class Request
|
||||
$path = $uri->getPath();
|
||||
|
||||
if ($query = $uri->getQuery()) {
|
||||
$path .= '?'.$query;
|
||||
$path .= '?' . $query;
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
@@ -319,185 +397,189 @@ class Request
|
||||
$request->getMethod(),
|
||||
$path,
|
||||
$request->getProtocolVersion(),
|
||||
join( "\r\n",$requestHeaders ),
|
||||
join("\r\n", $requestHeaders),
|
||||
$requestBody->getContents(),
|
||||
$response->getProtocolVersion(),
|
||||
$response->getStatusCode(),
|
||||
$response->getReasonPhrase(),
|
||||
join( "\r\n",$responseHeaders ),
|
||||
join("\r\n", $responseHeaders),
|
||||
$response->getBody()->getContents()
|
||||
);
|
||||
} );
|
||||
$this->handlerStack->push( $logger );
|
||||
});
|
||||
$this->handlerStack->push($logger);
|
||||
$this->options['handler'] = $this->handlerStack;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function attach(string $name,string $contents,string $filename = null,array $headers = [])
|
||||
public function attach(string $name, string $contents, string $filename = null, array $headers = [])
|
||||
{
|
||||
$this->options['multipart'] = array_filter( [
|
||||
$this->options['multipart'] = array_filter([
|
||||
'name' => $name,
|
||||
'contents' => $contents,
|
||||
'headers' => $headers,
|
||||
'filename' => $filename,
|
||||
] );
|
||||
]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function get(string $url,array $query = [])
|
||||
public function get(string $url, array $query = [])
|
||||
{
|
||||
$params= parse_url( $url,PHP_URL_QUERY );
|
||||
$params = parse_url($url, PHP_URL_QUERY);
|
||||
|
||||
parse_str( $params?:'',$result );
|
||||
parse_str($params ?: '', $result);
|
||||
|
||||
$this->options['query'] = array_merge( $result,$query );
|
||||
$this->options['query'] = array_merge($result, $query);
|
||||
|
||||
return $this->request( 'GET',$url,$query );
|
||||
return $this->request('GET', $url, $query);
|
||||
}
|
||||
|
||||
public function post(string $url,array $data = [])
|
||||
public function post(string $url, array $data = [])
|
||||
{
|
||||
$this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->request( 'POST',$url,$data );
|
||||
return $this->request('POST', $url, $data);
|
||||
}
|
||||
|
||||
public function patch(string $url,array $data = [])
|
||||
public function patch(string $url, array $data = [])
|
||||
{
|
||||
$this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->request( 'PATCH',$url,$data );
|
||||
return $this->request('PATCH', $url, $data);
|
||||
}
|
||||
|
||||
public function put(string $url,array $data = [])
|
||||
public function put(string $url, array $data = [])
|
||||
{
|
||||
$this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->request( 'PUT',$url,$data );
|
||||
return $this->request('PUT', $url, $data);
|
||||
}
|
||||
|
||||
public function delete(string $url,array $data = [])
|
||||
public function delete(string $url, array $data = [])
|
||||
{
|
||||
$this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->request( 'DELETE',$url,$data );
|
||||
return $this->request('DELETE', $url, $data);
|
||||
}
|
||||
|
||||
public function head(string $url,array $data = [])
|
||||
public function head(string $url, array $data = [])
|
||||
{
|
||||
$this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->request( 'HEAD',$url,$data );
|
||||
return $this->request('HEAD', $url, $data);
|
||||
}
|
||||
|
||||
public function options(string $url,array $data = [])
|
||||
public function options(string $url, array $data = [])
|
||||
{
|
||||
$this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->request( 'OPTIONS',$url,$data );
|
||||
return $this->request('OPTIONS', $url, $data);
|
||||
}
|
||||
|
||||
public function getAsync(string $url,$query = null,callable $success = null,callable $fail = null)
|
||||
public function getAsync(string $url, $query = null, callable $success = null, callable $fail = null)
|
||||
{
|
||||
is_callable( $query ) || $this->options['query'] = $query;
|
||||
is_callable($query) || $this->options['query'] = $query;
|
||||
|
||||
return $this->requestAsync( 'GET',$url,$query,$success,$fail );
|
||||
return $this->requestAsync('GET', $url, $query, $success, $fail);
|
||||
}
|
||||
|
||||
public function postAsync(string $url,$data = null,callable $success = null,callable $fail = null)
|
||||
public function postAsync(string $url, $data = null, callable $success = null, callable $fail = null)
|
||||
{
|
||||
is_callable( $data ) || $this->options[$this->bodyFormat] = $data;
|
||||
is_callable($data) || $this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->requestAsync( 'POST',$url,$data,$success,$fail );
|
||||
return $this->requestAsync('POST', $url, $data, $success, $fail);
|
||||
}
|
||||
|
||||
public function patchAsync(string $url,$data = null,callable $success = null,callable $fail = null)
|
||||
public function patchAsync(string $url, $data = null, callable $success = null, callable $fail = null)
|
||||
{
|
||||
is_callable( $data ) || $this->options[$this->bodyFormat] = $data;
|
||||
is_callable($data) || $this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->requestAsync( 'PATCH',$url,$data,$success,$fail );
|
||||
return $this->requestAsync('PATCH', $url, $data, $success, $fail);
|
||||
}
|
||||
|
||||
public function putAsync(string $url,$data = null,callable $success = null,callable $fail = null)
|
||||
public function putAsync(string $url, $data = null, callable $success = null, callable $fail = null)
|
||||
{
|
||||
is_callable( $data ) || $this->options[$this->bodyFormat] = $data;
|
||||
is_callable($data) || $this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->requestAsync( 'PUT',$url,$data,$success,$fail );
|
||||
return $this->requestAsync('PUT', $url, $data, $success, $fail);
|
||||
}
|
||||
|
||||
public function deleteAsync(string $url,$data = null,callable $success = null,callable $fail = null)
|
||||
public function deleteAsync(string $url, $data = null, callable $success = null, callable $fail = null)
|
||||
{
|
||||
is_callable( $data ) || $this->options[$this->bodyFormat] = $data;
|
||||
is_callable($data) || $this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->requestAsync( 'DELETE',$url,$data,$success,$fail );
|
||||
return $this->requestAsync('DELETE', $url, $data, $success, $fail);
|
||||
}
|
||||
|
||||
public function headAsync(string $url,$data = null,callable $success = null,callable $fail = null)
|
||||
public function headAsync(string $url, $data = null, callable $success = null, callable $fail = null)
|
||||
{
|
||||
is_callable( $data ) || $this->options[$this->bodyFormat] = $data;
|
||||
is_callable($data) || $this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->requestAsync( 'HEAD',$url,$data,$success,$fail );
|
||||
return $this->requestAsync('HEAD', $url, $data, $success, $fail);
|
||||
}
|
||||
|
||||
public function optionsAsync(string $url,$data = null,callable $success = null,callable $fail = null)
|
||||
public function optionsAsync(string $url, $data = null, callable $success = null, callable $fail = null)
|
||||
{
|
||||
is_callable( $data ) || $this->options[$this->bodyFormat] = $data;
|
||||
is_callable($data) || $this->options[$this->bodyFormat] = $data;
|
||||
|
||||
return $this->requestAsync( 'OPTIONS',$url,$data,$success,$fail );
|
||||
return $this->requestAsync('OPTIONS', $url, $data, $success, $fail);
|
||||
}
|
||||
|
||||
public function multiAsync(array $promises,callable $success = null,callable $fail = null)
|
||||
public function multiAsync(array $promises, callable $success = null, callable $fail = null)
|
||||
{
|
||||
$count = count( $promises );
|
||||
$count = count($promises);
|
||||
|
||||
$this->concurrency = $this->concurrency ?: $count;
|
||||
|
||||
$requests = function () use ($promises) {
|
||||
foreach ( $promises as $promise ) {
|
||||
foreach ($promises as $promise) {
|
||||
yield function () use ($promise) {
|
||||
return $promise;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
$fulfilled = function ($response,$index) use ($success) {
|
||||
if (!is_null( $success )) {
|
||||
$response = $this->response( $response );
|
||||
call_user_func_array( $success,[$response,$index] );
|
||||
$fulfilled = function ($response, $index) use ($success) {
|
||||
if (!is_null($success)) {
|
||||
$response = $this->response($response);
|
||||
call_user_func_array($success, [$response, $index]);
|
||||
}
|
||||
};
|
||||
|
||||
$rejected = function ($exception,$index) use ($fail) {
|
||||
if (!is_null( $fail )) {
|
||||
$exception = $this->exception( $exception );
|
||||
call_user_func_array( $fail,[$exception,$index] );
|
||||
$rejected = function ($exception, $index) use ($fail) {
|
||||
if (!is_null($fail)) {
|
||||
$exception = $this->exception($exception);
|
||||
call_user_func_array($fail, [$exception, $index]);
|
||||
}
|
||||
};
|
||||
|
||||
$pool = new Pool( $this->client,$requests(),[
|
||||
$pool = new Pool($this->client, $requests(), [
|
||||
'concurrency' => $this->concurrency,
|
||||
'fulfilled' => $fulfilled,
|
||||
'rejected' => $rejected,
|
||||
] );
|
||||
]);
|
||||
|
||||
$pool->promise();
|
||||
|
||||
return $pool;
|
||||
}
|
||||
|
||||
protected function request(string $method,string $url,array $options = [])
|
||||
protected function request(string $method, string $url, array $options = [])
|
||||
{
|
||||
isset( $this->options[$this->bodyFormat] ) && $this->options[$this->bodyFormat] = $options;
|
||||
if (isset($this->options[$this->bodyFormat])) {
|
||||
$this->options[$this->bodyFormat] = $options;
|
||||
} else {
|
||||
$this->options[$this->bodyFormat] = $this->pendingBody;
|
||||
}
|
||||
if ($this->isRemoveBodyFormat) {
|
||||
unset( $this->options[$this->bodyFormat] );
|
||||
unset($this->options[$this->bodyFormat]);
|
||||
}
|
||||
try {
|
||||
$response = $this->client->request( $method,$url,$this->options );
|
||||
return $this->response( $response );
|
||||
} catch ( ConnectException $e ) {
|
||||
throw new ConnectionException( $e->getMessage(),0,$e );
|
||||
$response = $this->client->request($method, $url, $this->options);
|
||||
return $this->response($response);
|
||||
} catch (ConnectException $e) {
|
||||
throw new ConnectionException($e->getMessage(), 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -510,50 +592,60 @@ class Request
|
||||
* @throws ConnectionException
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public function client(string $method,string $url,array $options = [])
|
||||
public function client(string $method, string $url, array $options = [])
|
||||
{
|
||||
if (isset($this->options[$this->bodyFormat])) {
|
||||
$this->options[$this->bodyFormat] = $options;
|
||||
} else {
|
||||
$this->options[$this->bodyFormat] = $this->pendingBody;
|
||||
}
|
||||
if ($this->isRemoveBodyFormat) {
|
||||
unset($this->options[$this->bodyFormat]);
|
||||
}
|
||||
try {
|
||||
if (empty( $options )) {
|
||||
if (empty($options)) {
|
||||
$options = $this->options;
|
||||
}
|
||||
$response = $this->client->request( $method,$url,$options );
|
||||
return $this->response( $response );
|
||||
} catch ( ConnectException $e ) {
|
||||
throw new ConnectionException( $e->getMessage(),0,$e );
|
||||
$response = $this->client->request($method, $url, $options);
|
||||
return $this->response($response);
|
||||
} catch (ConnectException $e) {
|
||||
throw new ConnectionException($e->getMessage(), 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 原生异常请求
|
||||
* 原生异步请求
|
||||
* @param string $method
|
||||
* @param string $url
|
||||
* @param array $options
|
||||
* @return Response
|
||||
* @throws ConnectionException
|
||||
*/
|
||||
public function clientAsync(string $method,string $url,array $options = [])
|
||||
public function clientAsync(string $method, string $url, array $options = [])
|
||||
{
|
||||
if (isset($this->options[$this->bodyFormat])) {
|
||||
$this->options[$this->bodyFormat] = $options;
|
||||
} else {
|
||||
$this->options[$this->bodyFormat] = $this->pendingBody;
|
||||
}
|
||||
if ($this->isRemoveBodyFormat) {
|
||||
unset($this->options[$this->bodyFormat]);
|
||||
}
|
||||
try {
|
||||
if (empty( $options )) {
|
||||
if (empty($options)) {
|
||||
$options = $this->options;
|
||||
}
|
||||
$response = $this->client->requestAsync( $method,$url,$options );
|
||||
return $this->response( $response );
|
||||
} catch ( ConnectException $e ) {
|
||||
throw new ConnectionException( $e->getMessage(),0,$e );
|
||||
$response = $this->client->requestAsync($method, $url, $options);
|
||||
return $this->response($response);
|
||||
} catch (ConnectException $e) {
|
||||
throw new ConnectionException($e->getMessage(), 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function requestAsync(
|
||||
string $method,
|
||||
string $url,
|
||||
$options = null,
|
||||
callable $success = null,
|
||||
callable $fail = null
|
||||
)
|
||||
protected function requestAsync(string $method, string $url, $options = null, callable $success = null, callable $fail = null)
|
||||
{
|
||||
if (is_callable( $options )) {
|
||||
if (is_callable($options)) {
|
||||
$successCallback = $options;
|
||||
$failCallback = $success;
|
||||
} else {
|
||||
@@ -561,55 +653,59 @@ class Request
|
||||
$failCallback = $fail;
|
||||
}
|
||||
|
||||
isset( $this->options[$this->bodyFormat] ) && $this->options[$this->bodyFormat] = $options;
|
||||
if (isset($this->options[$this->bodyFormat])) {
|
||||
$this->options[$this->bodyFormat] = $options;
|
||||
} else {
|
||||
$this->options[$this->bodyFormat] = $this->pendingBody;
|
||||
}
|
||||
|
||||
if ($this->isRemoveBodyFormat) {
|
||||
unset( $this->options[$this->bodyFormat] );
|
||||
unset($this->options[$this->bodyFormat]);
|
||||
}
|
||||
|
||||
try {
|
||||
$promise = $this->client->requestAsync( $method,$url,$this->options );
|
||||
$promise = $this->client->requestAsync($method, $url, $this->options);
|
||||
|
||||
$fulfilled = function ($response) use ($successCallback) {
|
||||
if (!is_null( $successCallback )) {
|
||||
$response = $this->response( $response );
|
||||
call_user_func_array( $successCallback,[$response] );
|
||||
if (!is_null($successCallback)) {
|
||||
$response = $this->response($response);
|
||||
call_user_func_array($successCallback, [$response]);
|
||||
}
|
||||
};
|
||||
|
||||
$rejected = function ($exception) use ($failCallback) {
|
||||
if (!is_null( $failCallback )) {
|
||||
$exception = $this->exception( $exception );
|
||||
call_user_func_array( $failCallback,[$exception] );
|
||||
if (!is_null($failCallback)) {
|
||||
$exception = $this->exception($exception);
|
||||
call_user_func_array($failCallback, [$exception]);
|
||||
}
|
||||
};
|
||||
|
||||
$promise->then( $fulfilled,$rejected );
|
||||
$promise->then($fulfilled, $rejected);
|
||||
|
||||
$this->promises[] = $promise;
|
||||
|
||||
return $promise;
|
||||
} catch ( ConnectException $e ) {
|
||||
throw new ConnectionException( $e->getMessage(),0,$e );
|
||||
} catch (ConnectException $e) {
|
||||
throw new ConnectionException($e->getMessage(), 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
public function wait()
|
||||
{
|
||||
if (!empty($this->promises)) {
|
||||
Promise\settle($this->promises)->wait();
|
||||
\GuzzleHttp\Promise\Utils($this->promises)->wait();
|
||||
}
|
||||
$this->promises = [];
|
||||
}
|
||||
|
||||
protected function response($response)
|
||||
{
|
||||
return new Response( $response );
|
||||
return new Response($response);
|
||||
}
|
||||
|
||||
protected function exception($exception)
|
||||
{
|
||||
return new RequestException( $exception );
|
||||
return new RequestException($exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class TokenBucket extends ThrottleAbstract
|
||||
|
||||
if ($token_left < 1) {
|
||||
$tmp = (int)ceil($duration / $max_requests);
|
||||
$this->wait_seconds = $tmp - ($micronow - $last_time) % $tmp;
|
||||
$this->wait_seconds = $tmp - intval(($micronow - $last_time)) % $tmp;
|
||||
return false;
|
||||
}
|
||||
$this->cur_requests = $max_requests - $token_left;
|
||||
|
||||
Reference in New Issue
Block a user