mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-09 01:35:35 +08:00
154 lines
5.9 KiB
PHP
154 lines
5.9 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace ZM\Event\SwooleEvent;
|
||
|
||
use Error;
|
||
use Exception;
|
||
use Swoole\Coroutine;
|
||
use Swoole\Http\Request;
|
||
use ZM\Annotation\Http\RequestMapping;
|
||
use ZM\Annotation\Swoole\OnRequestEvent;
|
||
use ZM\Annotation\Swoole\OnSwooleEvent;
|
||
use ZM\Annotation\Swoole\SwooleHandler;
|
||
use ZM\Config\ZMConfig;
|
||
use ZM\Console\Console;
|
||
use ZM\Container\Container;
|
||
use ZM\Context\Context;
|
||
use ZM\Context\ContextInterface;
|
||
use ZM\Event\EventDispatcher;
|
||
use ZM\Event\SwooleEvent;
|
||
use ZM\Exception\InterruptException;
|
||
use ZM\Http\Response;
|
||
use ZM\Utils\HttpUtil;
|
||
|
||
/**
|
||
* Class OnRequest
|
||
* @SwooleHandler("request")
|
||
*/
|
||
class OnRequest implements SwooleEvent
|
||
{
|
||
public function onCall(?Request $request, ?\Swoole\Http\Response $response)
|
||
{
|
||
$response = new Response($response);
|
||
foreach (ZMConfig::get('global')['http_header'] as $k => $v) {
|
||
$response->setHeader($k, $v);
|
||
}
|
||
unset(Context::$context[Coroutine::getCid()]);
|
||
Console::debug('Calling Swoole "request" event from fd=' . $request->fd);
|
||
set_coroutine_params(['request' => $request, 'response' => $response]);
|
||
|
||
$this->registerRequestContainerBindings($request, $response);
|
||
|
||
$dis1 = new EventDispatcher(OnRequestEvent::class);
|
||
$dis1->setRuleFunction(function ($v) {
|
||
return (bool) eval('return ' . $v->getRule() . ';');
|
||
});
|
||
|
||
$dis = new EventDispatcher(OnSwooleEvent::class);
|
||
$dis->setRuleFunction(function ($v) {
|
||
if ($v->getRule() == '') {
|
||
return strtolower($v->type) == 'request';
|
||
}
|
||
if (strtolower($v->type) == 'request' && eval('return ' . $v->getRule() . ';')) {
|
||
return true;
|
||
}
|
||
return false;
|
||
});
|
||
|
||
try {
|
||
$dis1->dispatchEvents($request, $response);
|
||
$dis->dispatchEvents($request, $response);
|
||
if ($dis->status === EventDispatcher::STATUS_NORMAL && $dis1->status === EventDispatcher::STATUS_NORMAL) {
|
||
$result = HttpUtil::parseUri($request, $response, $request->server['request_uri'], $node, $params);
|
||
if ($result === true) {
|
||
ctx()->setCache('params', $params);
|
||
$dispatcher = new EventDispatcher(RequestMapping::class);
|
||
$div = new RequestMapping($node['route']);
|
||
$div->params = $params;
|
||
$div->method = $node['method'];
|
||
$div->request_method = $node['request_method'];
|
||
$div->class = $node['class'];
|
||
$dispatcher->dispatchEvent($div, null, $params, $request, $response);
|
||
|
||
if (!$response->isEnd()) {
|
||
$this->response($response, $dispatcher->store);
|
||
}
|
||
}
|
||
}
|
||
if (!$response->isEnd()) {
|
||
HttpUtil::responseCodePage($response, 404);
|
||
}
|
||
} catch (InterruptException $e) {
|
||
// do nothing
|
||
} catch (Exception $e) {
|
||
$response->status(500);
|
||
Console::info(
|
||
$request->server['remote_addr'] . ':' . $request->server['remote_port'] .
|
||
' [' . $response->getStatusCode() . '] ' . $request->server['request_uri']
|
||
);
|
||
if (!$response->isEnd()) {
|
||
if (ZMConfig::get('global', 'debug_mode')) {
|
||
$response->end(zm_internal_errcode('E00023') . 'Internal server exception: ' . $e->getMessage());
|
||
} else {
|
||
$response->end(zm_internal_errcode('E00023') . 'Internal server error.');
|
||
}
|
||
}
|
||
Console::error(zm_internal_errcode('E00023') . 'Internal server exception (500), caused by ' . get_class($e) . ': ' . $e->getMessage());
|
||
Console::log($e->getTraceAsString(), 'gray');
|
||
} catch (Error $e) {
|
||
$response->status(500);
|
||
Console::info(
|
||
$request->server['remote_addr'] . ':' . $request->server['remote_port'] .
|
||
' [' . $response->getStatusCode() . '] ' . $request->server['request_uri']
|
||
);
|
||
if (!$response->isEnd()) {
|
||
$error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
|
||
if (ZMConfig::get('global', 'debug_mode')) {
|
||
$response->end(zm_internal_errcode('E00023') . 'Internal server error: ' . $error_msg);
|
||
} else {
|
||
$response->end(zm_internal_errcode('E00023') . 'Internal server error.');
|
||
}
|
||
}
|
||
Console::error(zm_internal_errcode('E00023') . 'Internal server error (500), caused by ' . get_class($e) . ': ' . $e->getMessage());
|
||
Console::log($e->getTraceAsString(), 'gray');
|
||
} finally {
|
||
container()->flush();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 注册请求容器绑定
|
||
*/
|
||
private function registerRequestContainerBindings(Request $request, Response $response): void
|
||
{
|
||
$container = Container::getInstance();
|
||
// $container->setLogPrefix("[Container#{$frame->fd}]");
|
||
$container->instance(Request::class, $request);
|
||
$container->bind(ContextInterface::class, function () {
|
||
return ctx();
|
||
});
|
||
$container->alias(ContextInterface::class, Context::class);
|
||
}
|
||
|
||
/**
|
||
* 返回响应
|
||
* @param mixed $result
|
||
*/
|
||
private function response(Response $response, $result): void
|
||
{
|
||
if (is_string($result)) {
|
||
$response->end($result);
|
||
} else {
|
||
try {
|
||
$response->header('Content-Type', 'application/json');
|
||
$response->end(json_encode($result, JSON_UNESCAPED_UNICODE));
|
||
} catch (Exception $e) {
|
||
Console::error('无法将响应转换为JSON:' . $e->getMessage());
|
||
$response->end(json_encode(zm_internal_errcode('E00023') . 'Internal server error.'));
|
||
}
|
||
}
|
||
}
|
||
}
|