Compare commits

...

8 Commits
1.0.0 ... 1.1.0

Author SHA1 Message Date
whale
9a28126765 add Middleware and release version 1.1.0 2020-03-29 16:29:02 +08:00
whale
c2fcdf9668 add Middleware 2020-03-25 22:41:47 +08:00
whale
6861d27629 add Middleware 2020-03-25 18:35:16 +08:00
whale
50a64d2d0b fix websocket close event 2020-03-20 14:50:12 +08:00
whale
80ec6ad030 update README.md 2020-03-19 18:34:43 +08:00
whale
a8ee9ee9c2 update README.md 2020-03-19 18:29:33 +08:00
whale
67a62415a0 update README.md 2020-03-19 18:27:55 +08:00
whale
4187bab913 add global_function and ZMRequest class 2020-03-19 17:43:27 +08:00
22 changed files with 458 additions and 49 deletions

View File

@@ -4,7 +4,7 @@
[![zhamao License](https://img.shields.io/hexpm/l/plug.svg?maxAge=2592000)](https://github.com/zhamao-robot/zhamao-framework/blob/master/LICENSE)
[![版本](https://img.shields.io/badge/version-2020.3.2-green.svg)]()
[![this counter](https://img.shields.io/github/search/zhamao-robot/zhamao-framework/this.svg)](https://github.com/zhamao-robot/zhamao-framework/search?q=this)
[![goto counter](https://img.shields.io/github/search/zhamao-robot/zhamao-framework/goto.svg)](https://github.com/zhamao-robot/zhamao-framework/search?q=goto)
[![TODO counter](https://img.shields.io/github/search/zhamao-robot/zhamao-framework/TODO.svg)](https://github.com/zhamao-robot/zhamao-framework/search?q=TODO)
一个异步、多平台兼容的 **聊天机器人** 框架。
@@ -47,9 +47,16 @@ Pages[https://framework.zhamao.xin/](https://framework.zhamao.xin/)
旧版框架并入了 `old` 分支,如果想继续使用旧版框架请移步分支。升级过程中如果遇到问题可以找作者。
## 贡献
## 贡献和捐赠
如果你在使用过程中发现任何问题,可以提交 Issue 或自行 Fork 后修改并提交 Pull Request。目前项目仅一人维护耗费精力较大所以非常欢迎对框架的贡献。
本项目为作者闲暇时间开发,如果觉得好用,不妨进行捐助~你的捐助会让我更加有动力完善插件,感谢你的支持!
我们会将捐赠的资金用于本项目驱动的炸毛机器人和框架文档的服务器开销上。
### 支付宝
![支付宝二维码](/resources/images/alipay_img.jpg)
## 关于
框架和 SDK 是 炸毛机器人 项目的核心框架开源部分。炸毛机器人3276124472是作者写的一个高性能机器人曾获全国计算机设计大赛一等奖。
@@ -57,4 +64,4 @@ Pages[https://framework.zhamao.xin/](https://framework.zhamao.xin/)
本项目在更行内容时,请及时关注 GitHub 动态,更新前请将自己的模块代码做好备份。
项目框架采用 Apache-2.0 协议开源,在分发或重写修改等操作时需遵守协议。项目模块部分(`Module` 文件夹) 在非借鉴框架内代码时可不遵守 Apache-2.0 协议进行分发和修改(声明版权)。
项目框架采用 Apache-2.0 协议开源,在分发或重写修改等操作时需遵守协议。项目模块部分(`Module` 文件夹) 在非借鉴框架内代码时可不遵守 Apache-2.0 协议进行分发和修改(声明版权)。

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,7 @@
<?php
//这里写你的全局函数
function phptest(){
echo "Nothing.\n";
}

View File

@@ -46,13 +46,12 @@ class ZMBuf
// Atomic可跨进程读写的原子计数任何地方均可使用
/** @var null|swoole_atomic */
static $info_level = null;//保存log等级的原子计数
/** @var swoole_atomic $reload_time */
public static $events = [];
/** @var Atomic[] */
public static $atomics;
public static $req_mapping = [];
public static $config = [];
public static $context = [];
static function get($name, $default = null) {
return self::$cache[$name] ?? $default;
@@ -117,4 +116,4 @@ class ZMBuf
self::$atomics[$k] = new Atomic($v);
}
}
}
}

View File

@@ -1,5 +1,8 @@
<?php
use Framework\ZMBuf;
use ZM\Utils\Context;
function classLoader($p) {
$filepath = getClassPath($p);
if ($filepath === null)
@@ -143,4 +146,20 @@ function matchArgs($pattern, $context) {
}
return $result;
} else return false;
}
}
function set_coroutine_params($array){
$cid = Co::getCid();
if($cid == -1) die("Cannot set coroutine params at none coroutine mode.");
ZMBuf::$context[$cid] = $array;
foreach(ZMBuf::$context as $c => $v) {
if(!Co::exists($c)) unset(ZMBuf::$context[$c]);
}
}
function context(){
$cid = Co::getCid();
if(isset(ZMBuf::$context[$cid])) {
return new Context(ZMBuf::$context[$cid], $cid);
} else return null;
}

View File

@@ -6,7 +6,7 @@ namespace Module\Example;
use Framework\Console;
use ZM\Annotation\CQ\CQCommand;
use ZM\Annotation\Http\Controller;
use ZM\Annotation\Http\Middleware;
use ZM\Annotation\Http\RequestMapping;
use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\Connection\CQConnection;
@@ -15,7 +15,6 @@ use ZM\ModBase;
/**
* Class Hello
* @package Module\Example
* @Controller("/view")
*/
class Hello extends ModBase
{
@@ -34,17 +33,11 @@ class Hello extends ModBase
}
/**
* @RequestMapping("/test/{ping}")
*/
public function ping($param){
return "You input id is: ".$param["ping"];
}
/**
* @RequestMapping("/test/pong")
* @RequestMapping("/test/ping")
* @Middleware("timer")
*/
public function pong(){
$this->response->end("ping");
return "pong";
}
/**
@@ -54,4 +47,4 @@ class Hello extends ModBase
Console::info("Unknown connection , I will close it.");
$this->connection->close();
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Module\Middleware;
use Framework\Console;
use ZM\Annotation\Http\After;
use ZM\Annotation\Http\Before;
use ZM\Annotation\Http\MiddlewareClass;
use ZM\Http\MiddlewareInterface;
/**
* Class AuthMiddleware
* 示例中间件:用于统计路由函数运行时间用的
* @package Module\Middleware
* @MiddlewareClass()
*/
class TimerMiddleware implements MiddlewareInterface
{
private $starttime;
/**
* @Before()
* @return bool
*/
public function onBefore() {
$this->starttime = microtime(true);
return true;
}
/**
* @After()
*/
public function onAfter() {
Console::info("Using " . round((microtime(true) - $this->starttime) * 1000, 2) . " ms.");
}
public function getName() { return "timer"; }
}

View File

@@ -5,12 +5,18 @@ namespace ZM\Annotation;
use Doctrine\Common\Annotations\AnnotationException;
use Doctrine\Common\Annotations\AnnotationReader;
use Framework\Console;
use Framework\ZMBuf;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use ZM\Annotation\CQ\{CQAfter, CQBefore, CQCommand, CQMessage, CQMetaEvent, CQNotice, CQRequest};
use ZM\Annotation\Http\After;
use ZM\Annotation\Http\Before;
use ZM\Annotation\Http\Controller;
use ZM\Annotation\Http\HandleException;
use ZM\Annotation\Http\Middleware;
use ZM\Annotation\Http\MiddlewareClass;
use ZM\Annotation\Http\RequestMapping;
use ZM\Annotation\Interfaces\CustomAnnotation;
use ZM\Annotation\Interfaces\Level;
@@ -22,6 +28,7 @@ use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\Annotation\Interfaces\Rule;
use ZM\Connection\WSConnection;
use ZM\Http\MiddlewareInterface;
use ZM\Utils\DataProvider;
class AnnotationParser
@@ -31,8 +38,7 @@ class AnnotationParser
* @throws ReflectionException
* @throws AnnotationException
*/
public static function registerMods()
{
public static function registerMods() {
self::loadAnnotationClasses();
$all_class = getAllClasses(WORKING_DIR . "/src/Module/", "Module");
ZMBuf::$req_mapping[0] = [
@@ -55,6 +61,32 @@ class AnnotationParser
DataProvider::addSaveBuffer($vs->buf_name, $vs->sub_folder);
} elseif ($vs instanceof InitBuffer) {
ZMBuf::set($vs->buf_name, []);
} elseif ($vs instanceof MiddlewareClass) {
Console::info("正在注册中间件 ".$vs->class);
$result = [
"class" => "\\" . $reflection_class->getName()
];
foreach ($methods as $vss) {
if ($vss->getName() == "getName") {
/** @var MiddlewareInterface $tmp */
$tmp = new $v();
$result["name"] = $tmp->getName();
continue;
}
$method_annotations = $reader->getMethodAnnotations($vss);
foreach ($method_annotations as $vsss) {
if ($vss instanceof Rule) $vss = self::registerRuleEvent($vsss, $vss, $reflection_class);
else $vss = self::registerMethod($vsss, $vss, $reflection_class);
//echo get_class($vsss) . PHP_EOL;
if ($vsss instanceof Before) $result["before"] = $vsss->method;
if ($vsss instanceof After) $result["after"] = $vsss->method;
if ($vsss instanceof HandleException) {
$result["exceptions"][$vsss->class_name] = $vsss->method;
}
}
}
ZMBuf::$events[MiddlewareClass::class][$result["name"]] = $result;
continue 2;
}
}
foreach ($methods as $vs) {
@@ -74,8 +106,9 @@ class AnnotationParser
elseif ($vss instanceof CustomAnnotation) ZMBuf::$events[get_class($vss)][] = $vss;
elseif ($vss instanceof CQBefore) ZMBuf::$events[CQBefore::class][$vss->cq_event][] = $vss;
elseif ($vss instanceof CQAfter) ZMBuf::$events[CQAfter::class][$vss->cq_event][] = $vss;
elseif ($vss instanceof OnStart) {
ZMBuf::$events[OnStart::class][]=$vss;
elseif ($vss instanceof OnStart) ZMBuf::$events[OnStart::class][] = $vss;
elseif ($vss instanceof Middleware) {
ZMBuf::$events[MiddlewareInterface::class][$vss->class][$vss->method] = $vss->middleware;
}
}
}
@@ -84,7 +117,7 @@ class AnnotationParser
ZMBuf::$req_mapping = $tree[0];
//给支持level的排个序
foreach (ZMBuf::$events as $class_name => $v) {
if ((new $class_name()) instanceof Level) {
if (is_a($class_name, Level::class, true)) {
for ($i = 0; $i < count(ZMBuf::$events[$class_name]) - 1; ++$i) {
for ($j = 0; $j < count(ZMBuf::$events[$class_name]) - $i - 1; ++$j) {
$l1 = ZMBuf::$events[$class_name][$j]->level;
@@ -100,8 +133,7 @@ class AnnotationParser
}
}
private static function getRuleCallback($rule_str)
{
private static function getRuleCallback($rule_str) {
$func = null;
$rule = $rule_str;
if ($rule != "") {
@@ -179,23 +211,20 @@ class AnnotationParser
return $func;
}
private static function registerRuleEvent(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class)
{
private static function registerRuleEvent(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class) {
$vss->callback = self::getRuleCallback($vss->getRule());
$vss->method = $method->getName();
$vss->class = $class->getName();
return $vss;
}
private static function registerMethod(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class)
{
private static function registerMethod(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class) {
$vss->method = $method->getName();
$vss->class = $class->getName();
return $vss;
}
private static function registerRequestMapping(RequestMapping $vss, ReflectionMethod $method, ReflectionClass $class, string $prefix)
{
private static function registerRequestMapping(RequestMapping $vss, ReflectionMethod $method, ReflectionClass $class, string $prefix) {
$array = ZMBuf::$req_mapping;
$uid = count($array);
$prefix_exp = explode("/", $prefix);
@@ -263,8 +292,7 @@ class AnnotationParser
ZMBuf::$req_mapping = $array;
}
private static function loadAnnotationClasses()
{
private static function loadAnnotationClasses() {
$class = getAllClasses(WORKING_DIR . "/src/ZM/Annotation/", "ZM\\Annotation");
foreach ($class as $v) {
$s = WORKING_DIR . '/src/' . str_replace("\\", "/", $v) . ".php";
@@ -277,8 +305,7 @@ class AnnotationParser
}
}
public static function genTree($items)
{
public static function genTree($items) {
$tree = array();
foreach ($items as $item)
if (isset($items[$item['pid']]))
@@ -287,4 +314,4 @@ class AnnotationParser
$tree[] = &$items[$item['id']];
return $tree;
}
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase;
/**
* Class After
* @package ZM\Annotation\Http
* @Annotation
* @Target("METHOD")
*/
class After extends AnnotationBase
{
}

View File

@@ -0,0 +1,19 @@
<?php
namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase;
/**
* Class Before
* @package ZM\Annotation\Http
* @Annotation
* @Target("METHOD")
*/
class Before extends AnnotationBase
{
}

View File

@@ -0,0 +1,23 @@
<?php
namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Target;
use Exception;
use ZM\Annotation\AnnotationBase;
/**
* Class HandleException
* @package ZM\Annotation\Http
* @Annotation
* @Target("METHOD")
*/
class HandleException extends AnnotationBase
{
/**
* @var string
*/
public $class_name = Exception::class;
}

View File

@@ -0,0 +1,24 @@
<?php
namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase;
/**
* Class Middleware
* @package ZM\Annotation\Http
* @Annotation
* @Target("METHOD")
*/
class Middleware extends AnnotationBase
{
/**
* @var string
* @Required()
*/
public $middleware;
}

View File

@@ -0,0 +1,19 @@
<?php
namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase;
/**
* Class MiddlewareClass
* @package ZM\Annotation\Http
* @Annotation
* @Target("CLASS")
*/
class MiddlewareClass extends AnnotationBase
{
}

View File

@@ -5,6 +5,7 @@ namespace ZM\Event;
use Co;
use Error;
use Exception;
use Framework\Console;
use Framework\ZMBuf;
@@ -28,6 +29,9 @@ class EventHandler
ZMUtil::stop();
return;
} catch(Error $e) {
var_export($e);
ZMUtil::stop();
}
break;
case "message":
@@ -112,4 +116,4 @@ class EventHandler
ZMBuf::unsetByValue("sent_api", $req["echo"]);
}
}
}
}

View File

@@ -5,10 +5,14 @@ namespace ZM\Event\Swoole;
use Closure;
use Doctrine\Common\Annotations\AnnotationException;
use Exception;
use Framework\ZMBuf;
use Swoole\Http\Request;
use ZM\Annotation\Http\MiddlewareClass;
use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\Http\MiddlewareInterface;
use ZM\Http\Response;
use ZM\ModBase;
use ZM\ModHandleType;
@@ -30,6 +34,10 @@ class RequestEvent implements SwooleEvent
$this->response = $response;
}
/**
* @return $this|SwooleEvent
* @throws Exception
*/
public function onActivate() {
ZMUtil::checkWait();
foreach (ZMBuf::globals("http_header") as $k => $v) {
@@ -80,16 +88,52 @@ class RequestEvent implements SwooleEvent
return $this;
}
set_coroutine_params(["request" => $this->request, "response" => $this->response, "params" => $params]);
if (in_array(strtoupper($this->request->server["request_method"]), $node["request_method"] ?? [])) { //判断目标方法在不在里面
$c_name = $node["class"];
/** @var ModBase $class */
$class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST);
$r = call_user_func_array([$class, $node["method"]], [$params]);
if (is_string($r) && !$this->response->isEnd()) $this->response->end($r);
if ($class->block_continue) return $this;
if ($this->response->isEnd()) return $this;
if (isset(ZMBuf::$events[MiddlewareInterface::class][$c_name][$node["method"]])) {
$middleware = ZMBuf::$events[MiddlewareInterface::class][$c_name][$node["method"]];
if(!isset(ZMBuf::$events[MiddlewareClass::class][$middleware])) throw new AnnotationException("Annotation parse error: Unknown MiddlewareClass named \"{$middleware}\"!");
$middleware = ZMBuf::$events[MiddlewareClass::class][$middleware];
$before = $middleware["class"];
$r = new $before();
$before_result = true;
if (isset($middleware["before"])) {
$before_result = call_user_func([$r, $middleware["before"]], $this->request, $this->response, $params);
if ($before_result !== false) $before_result = true;
}
if ($before_result) {
try {
/** @var ModBase $class */
$class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST);
$result = call_user_func_array([$class, $node["method"]], [$params]);
if (is_string($result) && !$this->response->isEnd()) $this->response->end($result);
if (!$this->response->isEnd()) goto eventCall;
} catch (Exception $e) {
if (!isset($middleware["exceptions"])) throw $e;
foreach($middleware["exceptions"] as $name => $method) {
if($e instanceof $name) {
call_user_func([$r, $method], $e, $this->request, $this->response, $params);
return $this;
}
}
throw $e;
}
}
if (isset($middleware["after"])) {
call_user_func([$r, $middleware["after"]], $this->request, $this->response, $params);
return $this;
}
} else {
/** @var ModBase $class */
$class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST);
$r = call_user_func_array([$class, $node["method"]], [$params]);
if (is_string($r) && !$this->response->isEnd()) $this->response->end($r);
if (!$this->response->isEnd()) goto eventCall;
}
}
eventCall:
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
if (strtolower($v->type) == "request" && $this->parseSwooleRule($v)) {
$c = $v->class;
@@ -127,7 +171,7 @@ class RequestEvent implements SwooleEvent
}
private function parseSwooleRule($v) {
switch (explode(":",$v->rule)[0]) {
switch (explode(":", $v->rule)[0]) {
case "containsGet":
case "containsPost":
if ($v->callback instanceof Closure) return call_user_func($v->callback, $this->request);
@@ -141,4 +185,4 @@ class RequestEvent implements SwooleEvent
}
return true;
}
}
}

View File

@@ -8,6 +8,7 @@ use Framework\ZMBuf;
use Swoole\Server;
use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\Connection\ConnectionManager;
use ZM\ModBase;
use ZM\ModHandleType;
use ZM\Utils\ZMUtil;
@@ -28,6 +29,7 @@ class WSCloseEvent implements SwooleEvent
*/
public function onActivate() {
ZMUtil::checkWait();
ConnectionManager::close($this->fd);
foreach(ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
if(strtolower($v->type) == "close" && $this->parseSwooleRule($v)) {
$c = $v->class;

View File

@@ -144,6 +144,10 @@ class WorkerStartEvent implements SwooleEvent
//加载Custom目录下的自定义的内部类
ConnectionManager::registerCustomClass();
//加载自定义的全局函数
if(file_exists(WORKING_DIR."/src/Custom/global_function.php"))
require_once WORKING_DIR."/src/Custom/global_function.php";
}
private function setAutosaveTimer($globals) {

View File

@@ -0,0 +1,10 @@
<?php
namespace ZM\Http;
interface MiddlewareInterface
{
public function getName();
}

View File

@@ -157,6 +157,11 @@ class Response
public function isEnd() { return $this->is_end; }
public function endWithStatus($status_code = 200, $content = null){
$this->status($status_code);
$this->end($content);
}
/**
* @param $filename
* @param $offset
@@ -226,4 +231,4 @@ class Response
}
}
}

71
src/ZM/Utils/Context.php Normal file
View File

@@ -0,0 +1,71 @@
<?php
namespace ZM\Utils;
use Swoole\Http\Request;
use Swoole\WebSocket\Frame;
use swoole_server;
use ZM\Http\Response;
class Context
{
private $server = null;
private $frame = null;
private $data = null;
private $request = null;
private $response = null;
private $cid;
public function __construct($param0, $cid) {
if (isset($param0["server"])) $this->server = $param0["server"];
if (isset($param0["frame"])) $this->frame = $param0["frame"];
if (isset($param0["data"])) $this->data = $param0["data"];
if (isset($param0["request"])) $this->request = $param0["request"];
if (isset($param0["response"])) $this->response = $param0["response"];
$this->cid = $cid;
}
/**
* @return swoole_server|null
*/
public function getServer() {
return $this->server;
}
/**
* @return Frame|null
*/
public function getFrame() {
return $this->frame;
}
/**
* @return array|null
*/
public function getData() {
return $this->data;
}
/**
* @return Request|null
*/
public function getRequest() {
return $this->request;
}
/**
* @return Response|null
*/
public function getResponse() {
return $this->response;
}
/**
* @return int|null
*/
public function getCid() {
return $this->cid;
}
}

View File

@@ -40,7 +40,7 @@ class DataProvider
return ZMBuf::globals("http_reverse_link");
}
private static function getJsonData(string $string) {
public static function getJsonData(string $string) {
if(!file_exists(self::getDataConfig().$string)) return [];
return json_decode(Co::readFile(self::getDataConfig().$string), true);
}

View File

@@ -0,0 +1,75 @@
<?php
namespace ZM\Utils;
use Swlib\Saber;
use Swoole\Coroutine\Http\Client;
class ZMRequest
{
/**
* 使用Swoole协程客户端发起HTTP GET请求
* @version 1.1
* 返回请求后的body
* 如果请求失败或返回状态不是200则返回 false
* @param $url
* @param array $headers
* @param array $set
* @param bool $return_body
* @return bool|string|Client
*/
public static function get($url, $headers = [], $set = [], $return_body = true) {
$parse = parse_url($url);
$cli = new Client($parse["host"], ($parse["scheme"] == "https" ? 443 : (isset($parse["port"]) ? $parse["port"] : 80)), ($parse["scheme"] == "https" ? true : false));
$cli->setHeaders($headers);
$cli->set($set == [] ? ['timeout' => 15.0] : $set);
$cli->get($parse["path"] . (isset($parse["query"]) ? "?" . $parse["query"] : ""));
if ($return_body) {
if ($cli->errCode != 0 || $cli->statusCode != 200) return false;
$a = $cli->body;
$cli->close();
return $a;
} else {
$cli->close();
return $cli;
}
}
/**
* 使用Swoole协程客户端发起HTTP POST请求
* 返回请求后的body
* 如果请求失败或返回状态不是200则返回 false
* @param $url
* @param array $header
* @param $data
* @param array $set
* @param bool $return_body
* @return bool|string|Client
*/
public static function post($url, array $header, $data, $set = [], $return_body = true) {
$parse = parse_url($url);
$cli = new Client($parse["host"], ($parse["scheme"] == "https" ? 443 : (isset($parse["port"]) ? $parse["port"] : 80)), ($parse["scheme"] == "https" ? true : false));
$cli->set($set == [] ? ['timeout' => 15.0] : $set);
$cli->setHeaders($header);
$cli->post($parse["path"] . (isset($parse["query"]) ? ("?" . $parse["query"]) : ""), $data);
if ($return_body) {
if ($cli->errCode != 0 || $cli->statusCode != 200) return false;
$a = $cli->body;
$cli->close();
return $a;
} else {
$cli->close();
return $cli;
}
}
/**
* @param $option
* @return Saber
*/
public static function session($option) {
return Saber::session($option);
}
}