mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-03-18 05:04:51 +08:00
Merge pull request #184 from zhamao-robot/plugin-update-pre
插件和 OneBot 12 适配器前置内容
This commit is contained in:
commit
2633e91d4d
@ -69,6 +69,11 @@ $config['plugin'] = [
|
||||
'load_dir' => 'plugins',
|
||||
];
|
||||
|
||||
/* 内部默认启用的插件 */
|
||||
$config['native_plugin'] = [
|
||||
'onebot12' => true,
|
||||
];
|
||||
|
||||
/* 静态文件读取器 */
|
||||
$config['file_server'] = [
|
||||
'enable' => true,
|
||||
|
||||
@ -15,7 +15,7 @@ class CheckConfigCommand extends Command
|
||||
|
||||
protected function handle(): int
|
||||
{
|
||||
$current_cfg = getcwd() . '/config/';
|
||||
$current_cfg = SOURCE_ROOT_DIR . '/config/';
|
||||
$remote_cfg = include FRAMEWORK_ROOT_DIR . '/config/global_old.php';
|
||||
if (file_exists($current_cfg . 'global.php')) {
|
||||
$this->check($remote_cfg, 'global.php');
|
||||
@ -38,11 +38,7 @@ class CheckConfigCommand extends Command
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $remote
|
||||
* @param mixed $local
|
||||
*/
|
||||
private function check($remote, $local)
|
||||
private function check(mixed $remote, mixed $local)
|
||||
{
|
||||
$local_file = include WORKING_DIR . '/config/' . $local;
|
||||
if ($local_file === true) {
|
||||
|
||||
@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Event\Listener;
|
||||
|
||||
use Choir\Http\HttpFactory;
|
||||
use Choir\Http\Stream;
|
||||
use OneBot\Driver\Event\Http\HttpRequestEvent;
|
||||
use OneBot\Http\HttpFactory;
|
||||
use OneBot\Http\Stream;
|
||||
use OneBot\Util\Singleton;
|
||||
use ZM\Annotation\AnnotationHandler;
|
||||
use ZM\Annotation\Framework\BindEvent;
|
||||
@ -33,9 +33,7 @@ class HttpEventListener
|
||||
// TODO: 这里有个bug,如果是用的Workerman+Fiber协程的话,有个前置协程挂起,这里获取到的Event是被挂起的Event对象,触发两次事件才能归正
|
||||
// 跑一遍 BindEvent 绑定了 HttpRequestEvent 的注解
|
||||
$handler = new AnnotationHandler(BindEvent::class);
|
||||
$handler->setRuleCallback(function (BindEvent $anno) {
|
||||
return $anno->event_class === HttpRequestEvent::class;
|
||||
});
|
||||
$handler->setRuleCallback(fn (BindEvent $anno) => $anno->event_class === HttpRequestEvent::class);
|
||||
$handler->handleAll($event);
|
||||
// dump($event->getResponse());
|
||||
$node = null;
|
||||
@ -51,14 +49,15 @@ class HttpEventListener
|
||||
$div = new Route($node['route']);
|
||||
$div->params = $params;
|
||||
$div->method = $node['method'];
|
||||
$div->request_method = $node['request_method'];
|
||||
// TODO:这里有个bug,逻辑上 request_method 应该是个数组,而不是字符串,但是这里 $node['method'] 是字符串,所以这里只能用字符串来判断
|
||||
// $div->request_method = $node['request_method'];
|
||||
$div->class = $node['class'];
|
||||
$starttime = microtime(true);
|
||||
$handler->handle($div, null, $params, $event->getRequest(), $event);
|
||||
if (is_string($val = $handler->getReturnVal()) || ($val instanceof \Stringable)) {
|
||||
$event->withResponse(HttpFactory::getInstance()->createResponse(200, null, [], Stream::create($val)));
|
||||
$event->withResponse(HttpFactory::createResponse(200, null, [], Stream::create($val)));
|
||||
} elseif ($event->getResponse() === null) {
|
||||
$event->withResponse(HttpFactory::getInstance()->createResponse(500));
|
||||
$event->withResponse(HttpFactory::createResponse(500));
|
||||
}
|
||||
logger()->warning('Used ' . round((microtime(true) - $starttime) * 1000, 3) . ' ms');
|
||||
break;
|
||||
@ -74,7 +73,7 @@ class HttpEventListener
|
||||
*
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function onRequest1(HttpRequestEvent $event)
|
||||
public function onRequest1(HttpRequestEvent $event): void
|
||||
{
|
||||
if ($event->getResponse() === null) {
|
||||
$response = HttpUtil::handleStaticPage($event->getRequest()->getUri()->getPath());
|
||||
|
||||
@ -4,65 +4,48 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Event\Listener;
|
||||
|
||||
use Choir\Http\HttpFactory;
|
||||
use OneBot\Driver\Event\WebSocket\WebSocketCloseEvent;
|
||||
use OneBot\Driver\Event\WebSocket\WebSocketMessageEvent;
|
||||
use OneBot\Driver\Event\WebSocket\WebSocketOpenEvent;
|
||||
use OneBot\Driver\Process\ProcessManager;
|
||||
use OneBot\Http\HttpFactory;
|
||||
use OneBot\Util\Singleton;
|
||||
use ZM\Annotation\AnnotationHandler;
|
||||
use ZM\Annotation\Framework\BindEvent;
|
||||
use ZM\Container\ContainerServicesProvider;
|
||||
use ZM\Process\ProcessStateManager;
|
||||
use ZM\Utils\ConnectionUtil;
|
||||
|
||||
class WSEventListener
|
||||
{
|
||||
use Singleton;
|
||||
|
||||
private static int $ws_counter = 0;
|
||||
|
||||
private static array $conn_handle = [];
|
||||
|
||||
public function onWebSocketOpen(WebSocketOpenEvent $event)
|
||||
/**
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function onWebSocketOpen(WebSocketOpenEvent $event): void
|
||||
{
|
||||
logger()->info('接入连接: ' . $event->getFd());
|
||||
// 计数,最多只能接入 1024 个连接,为了适配多进程
|
||||
++self::$ws_counter;
|
||||
if (self::$ws_counter >= 1024) {
|
||||
$event->withResponse(HttpFactory::getInstance()->createResponse(503));
|
||||
if (!ConnectionUtil::addConnection($event->getFd(), [])) {
|
||||
$event->withResponse(HttpFactory::createResponse(503));
|
||||
return;
|
||||
}
|
||||
// 注册容器
|
||||
resolve(ContainerServicesProvider::class)->registerServices('connection');
|
||||
// 判断是不是 OneBot 12 反向 WS 连进来的,通过 Sec-WebSocket-Protocol 头
|
||||
$line = explode('.', $event->getRequest()->getHeaderLine('Sec-WebSocket-Protocol'), 2);
|
||||
if ($line[0] === '12') {
|
||||
// 是 OneBot 12 标准的,准许接入,进行鉴权
|
||||
$request = $event->getRequest();
|
||||
if (($stored_token = $event->getSocketConfig()['access_token'] ?? '') !== '') {
|
||||
$token = $request->getHeaderLine('Authorization');
|
||||
$token = explode('Bearer ', $token);
|
||||
if (!isset($token[1]) || $token[1] !== $stored_token) { // 没有 token,鉴权失败
|
||||
$event->withResponse(HttpFactory::getInstance()->createResponse(401, 'Unauthorized'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 这里下面为连接准入,允许接入反向 WS,TODO
|
||||
if (ProcessStateManager::$process_mode['worker'] > 1) {
|
||||
// 如果开了多 Worker,则需要将连接信息写入文件,以便跨进程读取
|
||||
$info = ['impl' => $line[1] ?? 'unknown'];
|
||||
self::$conn_handle[$event->getFd()] = $info;
|
||||
file_put_contents(zm_dir(ZM_STATE_DIR . '/.WS' . $event->getFd() . '.' . ProcessManager::getProcessId()), json_encode($info));
|
||||
}
|
||||
}
|
||||
|
||||
// 调用注解
|
||||
$handler = new AnnotationHandler(BindEvent::class);
|
||||
$handler->setRuleCallback(fn ($x) => is_a($x->event_class, WebSocketOpenEvent::class, true));
|
||||
$handler->handleAll($event);
|
||||
}
|
||||
|
||||
public function onWebSocketClose(WebSocketCloseEvent $event)
|
||||
public function onWebSocketMessage(WebSocketMessageEvent $event): void
|
||||
{
|
||||
--self::$ws_counter;
|
||||
// 删除连接信息
|
||||
$fd = $event->getFd();
|
||||
$filename = zm_dir(ZM_STATE_DIR . '/.WS' . $fd . '.' . ProcessManager::getProcessId());
|
||||
if (file_exists($filename)) {
|
||||
unlink($filename);
|
||||
}
|
||||
unset(self::$conn_handle[$fd]);
|
||||
}
|
||||
|
||||
public function onWebSocketClose(WebSocketCloseEvent $event): void
|
||||
{
|
||||
logger()->info('关闭连接: ' . $event->getFd());
|
||||
ConnectionUtil::removeConnection($event->getFd());
|
||||
resolve(ContainerServicesProvider::class)->cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,8 @@ use ZM\Annotation\Framework\Init;
|
||||
use ZM\Container\ContainerServicesProvider;
|
||||
use ZM\Exception\ZMKnownException;
|
||||
use ZM\Framework;
|
||||
use ZM\Plugin\OneBot12Adapter;
|
||||
use ZM\Plugin\PluginManager;
|
||||
use ZM\Process\ProcessStateManager;
|
||||
use ZM\Store\Database\DBException;
|
||||
use ZM\Store\Database\DBPool;
|
||||
@ -134,6 +136,10 @@ class WorkerEventListener
|
||||
}
|
||||
|
||||
// TODO: 然后加载插件目录下的插件
|
||||
PluginManager::addPlugin([
|
||||
'name' => 'onebot12-adapter',
|
||||
'plugin' => new OneBot12Adapter(),
|
||||
]);
|
||||
|
||||
// 解析所有注册路径的文件,获取注解
|
||||
$parser->parseAll();
|
||||
|
||||
@ -4,6 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Exception;
|
||||
|
||||
/**
|
||||
* 初始化命令(./zhamao init)出现的错误
|
||||
*/
|
||||
class InitException extends ZMException
|
||||
{
|
||||
}
|
||||
|
||||
12
src/ZM/Exception/PluginException.php
Normal file
12
src/ZM/Exception/PluginException.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Exception;
|
||||
|
||||
/**
|
||||
* 插件加载器出现的错误
|
||||
*/
|
||||
class PluginException extends ZMException
|
||||
{
|
||||
}
|
||||
@ -12,16 +12,15 @@ use OneBot\Driver\Event\Process\ManagerStopEvent;
|
||||
use OneBot\Driver\Event\Process\WorkerStartEvent;
|
||||
use OneBot\Driver\Event\Process\WorkerStopEvent;
|
||||
use OneBot\Driver\Event\WebSocket\WebSocketCloseEvent;
|
||||
use OneBot\Driver\Event\WebSocket\WebSocketMessageEvent;
|
||||
use OneBot\Driver\Event\WebSocket\WebSocketOpenEvent;
|
||||
use OneBot\Driver\Interfaces\DriverInitPolicy;
|
||||
use OneBot\Driver\Swoole\SwooleDriver;
|
||||
use OneBot\Driver\Workerman\Worker;
|
||||
use OneBot\Driver\Workerman\WorkermanDriver;
|
||||
use OneBot\Util\Singleton;
|
||||
use Phar;
|
||||
use ZM\Command\Server\ServerStartCommand;
|
||||
use ZM\Config\ZMConfig;
|
||||
use ZM\Event\EventProvider;
|
||||
use ZM\Event\Listener\HttpEventListener;
|
||||
use ZM\Event\Listener\ManagerEventListener;
|
||||
use ZM\Event\Listener\MasterEventListener;
|
||||
@ -45,7 +44,7 @@ class Framework
|
||||
public const VERSION_ID = 633;
|
||||
|
||||
/** @var string 版本名称 */
|
||||
public const VERSION = '3.0.0-alpha4';
|
||||
public const VERSION = '3.0.0-alpha5';
|
||||
|
||||
/** @var array 传入的参数 */
|
||||
protected array $argv;
|
||||
@ -239,6 +238,7 @@ class Framework
|
||||
// websocket 事件
|
||||
ob_event_provider()->addEventListener(WebSocketOpenEvent::getName(), [WSEventListener::getInstance(), 'onWebSocketOpen'], 999);
|
||||
ob_event_provider()->addEventListener(WebSocketCloseEvent::getName(), [WSEventListener::getInstance(), 'onWebSocketClose'], 999);
|
||||
ob_event_provider()->addEventListener(WebSocketMessageEvent::getName(), [WSEventListener::getInstance(), 'onWebSocketMessage'], 999);
|
||||
|
||||
// 框架多进程依赖
|
||||
if (defined('ZM_STATE_DIR') && !is_dir(ZM_STATE_DIR)) {
|
||||
|
||||
49
src/ZM/Plugin/OneBot12Adapter.php
Normal file
49
src/ZM/Plugin/OneBot12Adapter.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin;
|
||||
|
||||
use Choir\Http\HttpFactory;
|
||||
use OneBot\Driver\Event\WebSocket\WebSocketOpenEvent;
|
||||
use ZM\Utils\ConnectionUtil;
|
||||
|
||||
class OneBot12Adapter extends ZMPlugin
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(__DIR__);
|
||||
$this->addEvent(WebSocketOpenEvent::class, [$this, 'handleWSReverseInput']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接入和认证反向 WS 的连接
|
||||
*/
|
||||
public function handleWSReverseInput(WebSocketOpenEvent $event): void
|
||||
{
|
||||
// 判断是不是 OneBot 12 反向 WS 连进来的,通过 Sec-WebSocket-Protocol 头
|
||||
$line = explode('.', $event->getRequest()->getHeaderLine('Sec-WebSocket-Protocol'), 2);
|
||||
if ($line[0] === '12') {
|
||||
logger()->info('检测到 OneBot 12 反向 WS 连接,正在进行认证...');
|
||||
// 是 OneBot 12 标准的,准许接入,进行鉴权
|
||||
$request = $event->getRequest();
|
||||
if (($stored_token = $event->getSocketConfig()['access_token'] ?? '') !== '') {
|
||||
// 测试 Header
|
||||
$token = $request->getHeaderLine('Authorization');
|
||||
if ($token === '') {
|
||||
// 测试 Query
|
||||
$token = $request->getQueryParams()['access_token'] ?? '';
|
||||
}
|
||||
$token = explode('Bearer ', $token);
|
||||
$info = ['impl' => $line[1] ?? 'unknown'];
|
||||
if (!isset($token[1]) || $token[1] !== $stored_token) { // 没有 token,鉴权失败
|
||||
logger()->warning('OneBot 12 反向 WS 连接鉴权失败,拒绝接入');
|
||||
$event->withResponse(HttpFactory::createResponse(401, 'Unauthorized'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设置 OneBot 相关的东西
|
||||
ConnectionUtil::setConnection($event->getFd(), $info ?? []);
|
||||
}
|
||||
}
|
||||
40
src/ZM/Plugin/PluginManager.php
Normal file
40
src/ZM/Plugin/PluginManager.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin;
|
||||
|
||||
use ZM\Exception\PluginException;
|
||||
|
||||
class PluginManager
|
||||
{
|
||||
/** @var array 插件信息列表 */
|
||||
private static array $plugins = [];
|
||||
|
||||
/**
|
||||
* @throws PluginException
|
||||
*/
|
||||
public static function addPlugin(array $meta = []): void
|
||||
{
|
||||
// 首先检测 meta 是否存在 plugin 对象
|
||||
if (isset($meta['plugin'])) {
|
||||
// 存在的话,说明是单例插件,调用对象内的方法注册事件就行了
|
||||
$meta['type'] = 'instant';
|
||||
self::$plugins[$meta['name']] = $meta;
|
||||
return;
|
||||
}
|
||||
if (isset($meta['dir'])) {
|
||||
// 不存在的话,说明是多文件插件,是设置了 zmplugin.json 的目录,此目录为自动加载的
|
||||
$meta['type'] = 'dir';
|
||||
self::$plugins[$meta['name']] = $meta;
|
||||
return;
|
||||
}
|
||||
// 两者都不存在的话,说明是错误的插件
|
||||
throw new PluginException('plugin meta must have plugin or dir');
|
||||
}
|
||||
|
||||
public static function getPlugins(): array
|
||||
{
|
||||
return self::$plugins;
|
||||
}
|
||||
}
|
||||
75
src/ZM/Utils/ConnectionUtil.php
Normal file
75
src/ZM/Utils/ConnectionUtil.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
use OneBot\Driver\Process\ProcessManager;
|
||||
use ZM\Process\ProcessStateManager;
|
||||
|
||||
class ConnectionUtil
|
||||
{
|
||||
/**
|
||||
* @internal
|
||||
* @var int WebSocket 连接统计
|
||||
*/
|
||||
public static int $connection_count = 0;
|
||||
|
||||
/**
|
||||
* @var array WebSocket 连接元信息
|
||||
*/
|
||||
private static array $connection_handles = [];
|
||||
|
||||
/**
|
||||
* 添加连接元信息
|
||||
*
|
||||
* @param int $fd WS 连接 ID
|
||||
* @param array $handle WS 连接元信息
|
||||
*/
|
||||
public static function addConnection(int $fd, array $handle = []): bool
|
||||
{
|
||||
++self::$connection_count;
|
||||
// 超过1024不行
|
||||
if (self::$connection_count >= 1024) {
|
||||
return false;
|
||||
}
|
||||
self::$connection_handles[$fd] = $handle;
|
||||
// 这里下面为连接准入,允许接入反向 WS
|
||||
if (ProcessStateManager::$process_mode['worker'] > 1) {
|
||||
// 文件名格式为 .WS{fd}.{pid},文件内容是 impl 名称的 JSON 格式
|
||||
file_put_contents(zm_dir(ZM_STATE_DIR . '/.WS' . $fd . '.' . ProcessManager::getProcessId()), json_encode($handle));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改、覆盖或合并连接元信息
|
||||
* @param int $fd WS 连接 ID
|
||||
* @param array $handle WS 连接元信息
|
||||
*/
|
||||
public static function setConnection(int $fd, array $handle): void
|
||||
{
|
||||
self::$connection_handles[$fd] = array_merge(self::$connection_handles[$fd] ?? [], $handle);
|
||||
// 这里下面为连接准入,允许接入反向 WS
|
||||
if (ProcessStateManager::$process_mode['worker'] > 1) {
|
||||
// 文件名格式为 .WS{fd}.{pid},文件内容是 impl 名称的 JSON 格式
|
||||
file_put_contents(zm_dir(ZM_STATE_DIR . '/.WS' . $fd . '.' . ProcessManager::getProcessId()), json_encode(self::$connection_handles[$fd]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除连接元信息
|
||||
*
|
||||
* @param int $fd WS 连接 ID
|
||||
*/
|
||||
public static function removeConnection(int $fd): void
|
||||
{
|
||||
--self::$connection_count;
|
||||
unset(self::$connection_handles[$fd]);
|
||||
// 这里下面为连接准入,允许接入反向 WS
|
||||
if (ProcessStateManager::$process_mode['worker'] > 1) {
|
||||
// 文件名格式为 .WS{fd}.{pid},文件内容是 impl 名称的 JSON 格式
|
||||
@unlink(zm_dir(ZM_STATE_DIR . '/.WS' . $fd . '.' . ProcessManager::getProcessId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
use OneBot\Http\HttpFactory;
|
||||
use OneBot\Http\ServerRequest;
|
||||
use OneBot\Http\Stream;
|
||||
use Choir\Http\HttpFactory;
|
||||
use Choir\Http\Stream;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
@ -32,7 +32,7 @@ class HttpUtil
|
||||
* 第二个参数为路由节点
|
||||
* 第三个参数为动态路由节点中匹配到的参数列表
|
||||
*/
|
||||
public static function parseUri(ServerRequest $request, mixed &$node, mixed &$params): int
|
||||
public static function parseUri(RequestInterface $request, mixed &$node, mixed &$params): int
|
||||
{
|
||||
// 建立上下文,设置当前请求的方法
|
||||
$context = new RequestContext();
|
||||
@ -90,7 +90,7 @@ class HttpUtil
|
||||
if ($path !== false) {
|
||||
// 安全问题,防止目录穿越,只能囚禁到规定的 Web 根目录下获取文件
|
||||
$work = realpath($base_dir) . '/';
|
||||
if (strpos($path, $work) !== 0) {
|
||||
if (!str_starts_with($path, $work)) {
|
||||
logger()->info('[403] ' . $uri);
|
||||
return static::handleHttpCodePage(403);
|
||||
}
|
||||
@ -98,25 +98,25 @@ class HttpUtil
|
||||
if (is_dir($path)) {
|
||||
if (mb_substr($uri, -1, 1) != '/') {
|
||||
logger()->info('[302] ' . $uri);
|
||||
return HttpFactory::getInstance()->createResponse(302, null, ['Location' => $uri . '/']);
|
||||
return HttpFactory::createResponse(302, null, ['Location' => $uri . '/']);
|
||||
}
|
||||
// 如果结尾有 /,那么就根据默认搜索的文件名进行搜索文件是否存在,存在则直接返回对应文件
|
||||
foreach ($base_index as $vp) {
|
||||
if (is_file($path . '/' . $vp)) {
|
||||
logger()->info('[200] ' . $uri);
|
||||
$exp = strtolower(pathinfo($path . $vp)['extension'] ?? 'unknown');
|
||||
return HttpFactory::getInstance()->createResponse()
|
||||
return HttpFactory::createResponse()
|
||||
->withAddedHeader('Content-Type', config('file_header')[$exp] ?? 'application/octet-stream')
|
||||
->withBody(HttpFactory::getInstance()->createStream(file_get_contents($path . '/' . $vp)));
|
||||
->withBody(HttpFactory::createStream(file_get_contents($path . '/' . $vp)));
|
||||
}
|
||||
}
|
||||
} elseif (is_file($path)) {
|
||||
// 如果文件存在,则直接返回文件内容
|
||||
logger()->info('[200] ' . $uri);
|
||||
$exp = strtolower(pathinfo($path)['extension'] ?? 'unknown');
|
||||
return HttpFactory::getInstance()->createResponse()
|
||||
return HttpFactory::createResponse()
|
||||
->withAddedHeader('Content-Type', config('file_header')[$exp] ?? 'application/octet-stream')
|
||||
->withBody(HttpFactory::getInstance()->createStream(file_get_contents($path)));
|
||||
->withBody(HttpFactory::createStream(file_get_contents($path)));
|
||||
}
|
||||
}
|
||||
// 否则最终肯定只能返回 404 了
|
||||
@ -137,9 +137,9 @@ class HttpUtil
|
||||
$code_page = null;
|
||||
}
|
||||
if ($code_page === null) {
|
||||
return HttpFactory::getInstance()->createResponse($code);
|
||||
return HttpFactory::createResponse($code);
|
||||
}
|
||||
return HttpFactory::getInstance()->createResponse($code, null, [], file_get_contents(config('global.file_server.document_root') . '/' . $code_page));
|
||||
return HttpFactory::createResponse($code, null, [], file_get_contents(config('global.file_server.document_root') . '/' . $code_page));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,7 +151,7 @@ class HttpUtil
|
||||
*/
|
||||
public static function createJsonResponse(array $data, int $http_code = 200, int $json_flag = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE): ResponseInterface
|
||||
{
|
||||
return HttpFactory::getInstance()->createResponse($http_code)
|
||||
return HttpFactory::createResponse($http_code)
|
||||
->withAddedHeader('Content-Type', 'application/json')
|
||||
->withBody(Stream::create(json_encode($data, $json_flag)));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user