Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
add async service for plugin
  • Loading branch information
joyqi committed Nov 15, 2017
1 parent 5f3620e commit f180e84
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 4 deletions.
11 changes: 11 additions & 0 deletions var/Helper.php
Expand Up @@ -63,6 +63,17 @@ public static function widgetById($table, $pkId)
return $widget;
}

/**
* 请求异步服务
*
* @param $method
* @param $params
*/
public static function requestService($method, $params)
{
Typecho_Widget::widget('Widget_Service')->requestService($method, $params);
}

/**
* 强行删除某个插件
*
Expand Down
35 changes: 34 additions & 1 deletion var/Typecho/Common.php
Expand Up @@ -22,7 +22,7 @@
class Typecho_Common
{
/** 程序版本 */
const VERSION = '1.1/17.10.30';
const VERSION = '1.1/17.11.15';

/**
* 允许的属性
Expand Down Expand Up @@ -910,6 +910,39 @@ public static function hashValidate($from, $to)
}
}

/**
* 创建一个会过期的Token
*
* @param $secret
* @return string
*/
public static function timeToken($secret)
{
return sha1($secret . '&' . time());
}

/**
* 在时间范围内验证token
*
* @param $token
* @param $secret
* @param int $timeout
* @return bool
*/
public static function timeTokenValidate($token, $secret, $timeout = 5)
{
$now = time();
$from = $now - $timeout;

for ($i = $now; $i >= $from; $i --) {
if (sha1($secret . '&' . $i) == $token) {
return true;
}
}

return false;
}

/**
* 将路径转化为链接
*
Expand Down
39 changes: 39 additions & 0 deletions var/Typecho/Response.php
Expand Up @@ -87,6 +87,13 @@ class Typecho_Response
*/
private static $_instance = null;

/**
* 结束前回调函数
*
* @var array
*/
private static $_callbacks = array();

/**
* 获取单例句柄
*
Expand Down Expand Up @@ -126,6 +133,33 @@ private function _parseXml($message)
}
}

/**
* 结束前的统一回调函数
*/
public static function callback()
{
static $called;

if ($called) {
return;
}

$called = true;
foreach (self::$_callbacks as $callback) {
call_user_func($callback);
}
}

/**
* 新增回调
*
* @param $callback
*/
public static function addCallback($callback)
{
self::$_callbacks[] = $callback;
}

/**
* 设置默认回执编码
*
Expand Down Expand Up @@ -211,6 +245,7 @@ public function throwXml($message)
'</response>';

/** 终止后续输出 */
self::callback();
exit;
}

Expand All @@ -229,6 +264,7 @@ public function throwJson($message)
echo Json::encode($message);

/** 终止后续输出 */
self::callback();
exit;
}

Expand All @@ -246,9 +282,11 @@ public function redirect($location, $isPermanently = false)
$location = Typecho_Common::safeUrl($location);

if ($isPermanently) {
self::callback();
header('Location: ' . $location, false, 301);
exit;
} else {
self::callback();
header('Location: ' . $location, false, 302);
exit;
}
Expand Down Expand Up @@ -296,6 +334,7 @@ public function goBack($suffix = NULL, $default = NULL)
$this->redirect($default);
}

self::callback();
exit;
}
}
1 change: 1 addition & 0 deletions var/Typecho/Router.php
Expand Up @@ -138,6 +138,7 @@ public static function dispatch()
$widget->{$route['action']}();
}

Typecho_Response::callback();
return;

} catch (Exception $e) {
Expand Down
2 changes: 1 addition & 1 deletion var/Widget/Ajax.php
Expand Up @@ -51,7 +51,7 @@ public function checkVersion()

/** 匹配内容体 */
$response = $client->getResponseBody();
$json = json_decode($response, true);
$json = Json::decode($response, true);

if (!empty($json)) {
list($soft, $version) = explode(' ', $this->options->generator);
Expand Down
90 changes: 88 additions & 2 deletions var/Widget/Service.php
Expand Up @@ -19,6 +19,13 @@
*/
class Widget_Service extends Widget_Abstract_Options implements Widget_Interface_Do
{
/**
* 异步请求
*
* @var array
*/
public $asyncRequests = array();

/**
* 发送pingback实现
*
Expand All @@ -31,7 +38,13 @@ public function sendPingHandle()
$this->user->pass('contributor');

/** 忽略超时 */
ignore_user_abort(true);
if (function_exists('ignore_user_abort')) {
ignore_user_abort(true);
}

if (function_exists('set_time_limit')) {
set_time_limit(30);
}

/** 获取post */
$post = $this->widget('Widget_Archive', "type=post", "cid={$this->request->cid}");
Expand Down Expand Up @@ -138,7 +151,7 @@ public function sendPing($cid, array $trackback = NULL)
$client->setCookie('__typecho_uid', Typecho_Cookie::get('__typecho_uid'))
->setCookie('__typecho_authCode', Typecho_Cookie::get('__typecho_authCode'))
->setHeader('User-Agent', $this->options->generator)
->setTimeout(3)
->setTimeout(2)
->setData($input)
->send(Typecho_Common::url('/action/service', $this->options->index));

Expand All @@ -148,6 +161,78 @@ public function sendPing($cid, array $trackback = NULL)
}
}

/**
* 请求异步服务
*
* @param $method
* @param mixed $params
*/
public function requestService($method, $params = NULL)
{
static $called;

if (!$called) {
$self = $this;

Typecho_Response::addCallback(function () use ($self) {
if (!empty($self->asyncRequests) && $client = Typecho_Http_Client::get()) {
try {
$client->setHeader('User-Agent', $this->options->generator)
->setTimeout(2)
->setData(array(
'do' => 'async',
'requests' => Json::encode($self->asyncRequests),
'token' => Typecho_Common::timeToken($this->options->secret)
))
->setMethod(Typecho_Http_Client::METHOD_POST)
->send(Typecho_Common::url('/action/service', $this->options->index));

} catch (Typecho_Http_Client_Exception $e) {
return;
}
}
});

$called = true;
}

$this->asyncRequests[] = array($method, $params);
}

/**
* 执行回调
*
* @throws Typecho_Widget_Exception
*/
public function asyncHandle()
{
/** 验证权限 */
$token = $this->request->token;

if (!Typecho_Common::timeTokenValidate($token, $this->options->secret, 3)) {
throw new Typecho_Widget_Exception(_t('禁止访问'), 403);
}

/** 忽略超时 */
if (function_exists('ignore_user_abort')) {
ignore_user_abort(true);
}

if (function_exists('set_time_limit')) {
set_time_limit(30);
}

$requests = Json::decode($this->request->requests, true);
$plugin = Typecho_Plugin::factory(__CLASS__);

if (!empty($requests)) {
foreach ($requests as $request) {
list ($method, $params) = $request;
$plugin->{$method}($params);
}
}
}

/**
* 异步请求入口
*
Expand All @@ -157,5 +242,6 @@ public function sendPing($cid, array $trackback = NULL)
public function action()
{
$this->on($this->request->is('do=ping'))->sendPingHandle();
$this->on($this->request->is('do=async'))->asyncHandle();
}
}

0 comments on commit f180e84

Please sign in to comment.