Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: swlib/saber
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.4
Choose a base ref
...
head repository: swlib/saber
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Loading
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -10,3 +10,4 @@ temp/
*.lock
/tools
/debug
.phpunit.*
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -120,7 +120,6 @@ go(function () {
- <a href="#swlibsaberwebsocket">Swlib\Saber\WebSocket</a>
- <a href="#swlibsaberwebsocketframe">Swlib\Saber\WebSocketFrame</a>


------

## 例子
@@ -214,10 +213,11 @@ echo $saber->requests([
'http://httpbin.org/html'
]
]);
var_dump($json->getParsedJson());
var_dump($json->getParsedJsonArray());
var_dump($json->getParsedJsonObject());
var_dump($xml->getParsedXml());
var_dump($html->getParsedHtml()->getElementsByTagName('h1')->item(0)->textContent);
var_dump($xml->getParsedXmlArray());
var_dump($xml->getParsedXmlObject(true));
var_dump($html->getParsedDomObject()->getElementsByTagName('h1')->item(0)->textContent);
```

### 网络代理
@@ -284,14 +284,20 @@ if ($response->success) {

`Saber`内置了此功能, 并可使用`拦截器`来强化它.

如未设置`retry_time`而设置了`retry`拦截器, 则`retry_time`会置为1, 如`retry`拦截器的回调方法返回了`false`, 无论`retry_time`是多少, 都会在返回`false`时终止重试.

```PHP
$uri = 'http://eu.httpbin.org/basic-auth/foo/bar';
$res = SaberGM::get(
$uri, [
'exception_report' => 0,
'retry_time' => 3,
'retry' => function (Saber\Request $request) {
echo "retry...\n";
$request->withBasicAuth('foo', 'bar'); //发现失败后添加验证信息
if ('i don not want to retry again') {
return false; // shutdown
}
}
]
);
@@ -358,7 +364,7 @@ go(function () {
```php
echo SaberGM::list([
'uri' => [
'http://www.qq.com/',
'https://www.qq.com/',
'https://www.baidu.com/',
'https://www.swoole.com/',
'http://httpbin.org/'
@@ -372,7 +378,7 @@ echo SaberGM::list([

```php
// max_co is the max number of concurrency request once, it's very useful to prevent server-waf limit.
$requests = array_fill(0, 10, ['uri' => 'http://www.qq.com/']);
$requests = array_fill(0, 10, ['uri' => 'https://www.qq.com/']);
echo SaberGM::requests($requests, ['max_co' => 5])->time."\n";
echo SaberGM::requests($requests, ['max_co' => 1])->time."\n";
```
@@ -443,13 +449,14 @@ go(function(){

## 配置参数表

`|`符号分割多种可选值
> `|`符号分割多种可选值
| key | type | introduction | example | remark |
| --------------------- | --------------------- | ------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| protocol_version | string | HTTP协议版本 | 1.1 | HTTP2还在规划中 |
| base_uri | string | 基础路径 | `http://httpbin.org` | 将会与uri按照rfc3986合并 |
| uri | string | 资源标识符 | `http://httpbin.org/get` \| `/get` \| `get` | 可以使用绝对路径和相对路径 |
| uri_query | string\|array | 请求信息 | `['foo' => 'bar']` | 非字符串会自动转换 |
| method | string | 请求方法 | `get` \| `post` \| `head` \| `patch` \| `put` \| `delete` | 底层自动转换为大写 |
| headers | array | 请求报头 | `['DNT' => '1']` \| `['accept' => ['text/html'], ['application/xml']]` | 字段名不区分大小写, 但会保留设定时的原始大小写规则, 底层每个字段值会根据PSR-7自动分割为数组 |
| cookies | `array`\|`string` | | `['foo '=> 'bar']` \| `'foo=bar; foz=baz'` | 底层自动转化为Cookies对象, 并设置其domain为当前的uri, 具有[浏览器级别的完备属性](#cookies). |
@@ -473,7 +480,7 @@ go(function(){
| exception_handle | callable\|array | 异常自定义处理函数 | `function(Exception $e){}` | 函数返回true时可忽略错误 |
| retry | callable | 自动重试拦截器 | `function(Request $request, Response $response){}` | 位于发生错误后及重试之前 |
| retry_time | int | 自动重试次数 | | 默认不重试 |
| use_pool | bool\|int | 连接池 | `true`| `false` |`100` | 是否启用连接池, 为数字时可限制连接池最大容量 |
| use_pool | bool\|int | 连接池 | `true` | `false` |

### 配置参数别名

@@ -599,7 +606,7 @@ Saber遵循将**业务与错误**分离的守则, 当请求任意环节失败时
| Exception | Intro | scene |
| ------------------------- | ------------------ | ------------------------------------------------------------ |
| RequestException | 请求失败 | 请求配置错误 |
| ConnectException | 连接失败 | 如无网络连接, DNS查询失败, 超时等, errno的值等于Linux errno。可使用socket_strerror将错误码转为错误信息|
| ConnectException | 连接失败 | 如无网络连接, DNS查询失败, 超时等, errno的值等于Linux errno。可使用swoole_strerror将错误码转为错误信息|
| TooManyRedirectsException | 重定向次数超限 | 重定向的次数超过了设定的限制, 抛出的异常将会打印重定向追踪信息 |
| ClientException | 客户端异常 | 服务器返回了4xx错误码 |
| ServerException | 服务器异常 | 服务器返回了5xx错误码 |
17 changes: 5 additions & 12 deletions composer.json
Original file line number Diff line number Diff line change
@@ -26,8 +26,11 @@
},
"require": {
"php": ">=7.0",
"swlib/http": "1.0.1",
"swlib/util": "1.0.0"
"swlib/http": "dev-master",
"swlib/util": "dev-master"
},
"require-dev": {
"phpunit/phpunit": "~7"
},
"autoload": {
"classmap": [
@@ -41,16 +44,6 @@
"src/include/functions.php"
]
},
"repositories": {
"packagist": {
"type": "composer",
"url": "https://packagist.laravel-china.org/"
}
},
"require-dev": {
"eaglewu/swoole-ide-helper": "dev-master",
"phpunit/phpunit": "~7"
},
"config": {
"optimize-autoloader": true,
"sort-packages": true
2 changes: 1 addition & 1 deletion examples/download.php
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
'https://ws1.sinaimg.cn/large/006DQdzWly1fsr8jt2botj31hc0wxqfs.jpg',
$download_dir
);
if ($response->success) {
if ($response->getSuccess()) {
exec('open ' . $download_dir);
}
});
4 changes: 2 additions & 2 deletions examples/interceptor.php
Original file line number Diff line number Diff line change
@@ -17,12 +17,12 @@
echo "log: request $uri now...\n";
},
'after' => function (Saber\Response $response) {
if ($response->success) {
if ($response->getSuccess()) {
echo "log: success!\n";
} else {
echo "log: failed\n";
}
echo "use {$response->time}s";
echo "use {$response->getTime()}s";
}
]);
});
2 changes: 1 addition & 1 deletion examples/list.php
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
go(function () {
$res = SaberGM::list([
'uri' => [
'http://www.qq.com/',
'https://www.qq.com/',
'https://www.baidu.com/',
'https://www.swoole.com/',
'http://eu.httpbin.org/'
4 changes: 2 additions & 2 deletions examples/mark.php
Original file line number Diff line number Diff line change
@@ -12,8 +12,8 @@
go(function () {
//it's the way to bind some special request data to response.
$responses = SaberGM::requests([
['uri' => 'http://www.qq.com/', 'mark' => 'it is request one!'],
['uri' => 'http://www.qq.com']
['uri' => 'https://www.qq.com/', 'mark' => 'it is request one!'],
['uri' => 'https://www.qq.com']
]);
echo $responses[0]->getSpecialMark();
});
2 changes: 1 addition & 1 deletion examples/max-concurrency-control.php
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@

go(function () {
// max_co is the max number of concurrency request once, it's very useful to prevent server-waf limit.
$requests = array_fill(0, 10, ['uri' => 'http://www.qq.com/']);
$requests = array_fill(0, 10, ['uri' => 'https://www.qq.com/']);
echo SaberGM::requests($requests, ['max_co' => 5])->time."\n";
echo SaberGM::requests($requests, ['max_co' => 1])->time."\n";
});
2 changes: 1 addition & 1 deletion examples/multi-vs-single.php
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@

$response = SaberGM::request(['uri' => 'https://github.com/']);
echo "single-request [ status: {$response->statusCode} ]: \n" .
"consuming-time: {$response->time}s\n";
"consuming-time: {$response->getTime()}s\n";

echo str_repeat("=", 20) . "\n";

16 changes: 8 additions & 8 deletions examples/pool.php
Original file line number Diff line number Diff line change
@@ -11,24 +11,24 @@

go(function () {
$pool = Saber::create([
'base_uri' => 'http://www.qq.com',
'base_uri' => 'https://www.qq.com',
'use_pool' => true
]);
$start = microtime(true);
assert($pool->get('/')->success, true);
assert($pool->get('/contract.shtml')->success, true);
assert($pool->get('/dzwfggcns.htm')->success, true);
assert($pool->get('/')->getSuccess(), true);
assert($pool->get('/contract.shtml')->getSuccess(), true);
assert($pool->get('/dzwfggcns.htm')->getSuccess(), true);
$pool_time = microtime(true) - $start;
var_dump($pool_time);

$not_pool = Saber::create([
'base_uri' => 'http://www.qq.com',
'base_uri' => 'https://www.qq.com',
'use_pool' => false
]);
$start = microtime(true);
assert($not_pool->get('/')->success, true);
assert($not_pool->get('/contract.shtml')->success, true);
assert($not_pool->get('/dzwfggcns.htm')->success, true);
assert($not_pool->get('/')->getSuccess(), true);
assert($not_pool->get('/contract.shtml')->getSuccess(), true);
assert($not_pool->get('/dzwfggcns.htm')->getSuccess(), true);
$not_pool_time = microtime(true) - $start;
var_dump($not_pool_time);

2 changes: 1 addition & 1 deletion examples/redirect.php
Original file line number Diff line number Diff line change
@@ -12,5 +12,5 @@
go(function () {
$uri = 'http://t.cn/Rn3tRyK';
$res = SaberGM::get($uri);
var_dump($res->redirect_headers);
var_dump($res->getRedirectHeaders());
});
3 changes: 1 addition & 2 deletions examples/stress.php
Original file line number Diff line number Diff line change
@@ -25,14 +25,13 @@
go(function () use ($server) {
SaberGM::default(['use_pool' => true]);
$requests = array_fill(0, 6666, ['uri' => 'http://127.0.0.1:1234']);
$res = SaberGM::requests($requests, ['max_co' => ((int)(`ulimit -n`) / 2)]);
$res = SaberGM::requests($requests, ['max_co' => 1111]);
echo "use {$res->time}s\n";
echo "success: $res->success_num, error: $res->error_num\n";
// on MacOS
// use 0.91531705856323s
// success: 6666, error: 0
saber_pool_release();
swoole_event_exit();
$server->shutdown();
});
}
12 changes: 8 additions & 4 deletions src/ClientPool.php
Original file line number Diff line number Diff line change
@@ -6,16 +6,20 @@

namespace Swlib\Saber;

use BadMethodCallException;
use InvalidArgumentException;
use Swlib\Util\MapPool;
use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
use Swoole\Coroutine\Http\Client;

class ClientPool extends \Swlib\Util\MapPool
class ClientPool extends MapPool
{

public function createEx(array $options, bool $temp = false)
{
if (\Swoole\Coroutine::getuid() < 0) {
throw new \BadMethodCallException(
if (Coroutine::getuid() < 0) {
throw new BadMethodCallException(
'You can only use coroutine client in `go` function or some Event callback functions.' . PHP_EOL .
'Please check https://wiki.swoole.com/wiki/page/696.html'
);
@@ -66,7 +70,7 @@ public function putEx(Client $client)
{
/** @var $client Client */
if (!($client instanceof Client)) {
throw new \InvalidArgumentException('$value should be instance of ' . Client::class);
throw new InvalidArgumentException('$value should be instance of ' . Client::class);
}
parent::put($client, "{$client->host}:{$client->port}");
}
Loading