mirror of
https://github.com/typecho/typecho.git
synced 2025-02-26 07:33:03 +01:00
add async service for plugin
This commit is contained in:
parent
5f3620e058
commit
f180e8452d
@ -63,6 +63,17 @@ class Helper
|
||||
return $widget;
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求异步服务
|
||||
*
|
||||
* @param $method
|
||||
* @param $params
|
||||
*/
|
||||
public static function requestService($method, $params)
|
||||
{
|
||||
Typecho_Widget::widget('Widget_Service')->requestService($method, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 强行删除某个插件
|
||||
*
|
||||
|
@ -22,7 +22,7 @@ define('__TYPECHO_MB_SUPPORTED__', function_exists('mb_get_info') && function_ex
|
||||
class Typecho_Common
|
||||
{
|
||||
/** 程序版本 */
|
||||
const VERSION = '1.1/17.10.30';
|
||||
const VERSION = '1.1/17.11.15';
|
||||
|
||||
/**
|
||||
* 允许的属性
|
||||
@ -910,6 +910,39 @@ EOF;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个会过期的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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将路径转化为链接
|
||||
*
|
||||
|
@ -87,6 +87,13 @@ class Typecho_Response
|
||||
*/
|
||||
private static $_instance = null;
|
||||
|
||||
/**
|
||||
* 结束前回调函数
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $_callbacks = array();
|
||||
|
||||
/**
|
||||
* 获取单例句柄
|
||||
*
|
||||
@ -126,6 +133,33 @@ class Typecho_Response
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束前的统一回调函数
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认回执编码
|
||||
*
|
||||
@ -211,6 +245,7 @@ class Typecho_Response
|
||||
'</response>';
|
||||
|
||||
/** 终止后续输出 */
|
||||
self::callback();
|
||||
exit;
|
||||
}
|
||||
|
||||
@ -229,6 +264,7 @@ class Typecho_Response
|
||||
echo Json::encode($message);
|
||||
|
||||
/** 终止后续输出 */
|
||||
self::callback();
|
||||
exit;
|
||||
}
|
||||
|
||||
@ -246,9 +282,11 @@ class Typecho_Response
|
||||
$location = Typecho_Common::safeUrl($location);
|
||||
|
||||
if ($isPermanently) {
|
||||
self::callback();
|
||||
header('Location: ' . $location, false, 301);
|
||||
exit;
|
||||
} else {
|
||||
self::callback();
|
||||
header('Location: ' . $location, false, 302);
|
||||
exit;
|
||||
}
|
||||
@ -296,6 +334,7 @@ class Typecho_Response
|
||||
$this->redirect($default);
|
||||
}
|
||||
|
||||
self::callback();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,7 @@ class Typecho_Router
|
||||
$widget->{$route['action']}();
|
||||
}
|
||||
|
||||
Typecho_Response::callback();
|
||||
return;
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
@ -51,7 +51,7 @@ class Widget_Ajax extends Widget_Abstract_Options implements Widget_Interface_Do
|
||||
|
||||
/** 匹配内容体 */
|
||||
$response = $client->getResponseBody();
|
||||
$json = json_decode($response, true);
|
||||
$json = Json::decode($response, true);
|
||||
|
||||
if (!empty($json)) {
|
||||
list($soft, $version) = explode(' ', $this->options->generator);
|
||||
|
@ -19,6 +19,13 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit;
|
||||
*/
|
||||
class Widget_Service extends Widget_Abstract_Options implements Widget_Interface_Do
|
||||
{
|
||||
/**
|
||||
* 异步请求
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $asyncRequests = array();
|
||||
|
||||
/**
|
||||
* 发送pingback实现
|
||||
*
|
||||
@ -31,7 +38,13 @@ class Widget_Service extends Widget_Abstract_Options implements Widget_Interface
|
||||
$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}");
|
||||
@ -138,7 +151,7 @@ class Widget_Service extends Widget_Abstract_Options implements Widget_Interface
|
||||
$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));
|
||||
|
||||
@ -148,6 +161,78 @@ class Widget_Service extends Widget_Abstract_Options implements Widget_Interface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求异步服务
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步请求入口
|
||||
*
|
||||
@ -157,5 +242,6 @@ class Widget_Service extends Widget_Abstract_Options implements Widget_Interface
|
||||
public function action()
|
||||
{
|
||||
$this->on($this->request->is('do=ping'))->sendPingHandle();
|
||||
$this->on($this->request->is('do=async'))->asyncHandle();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user