NOW_TIME
NOW_TIME = $request->server['request_time']
file:HttpRpcServer.php This file is part of J-Game.
HttpRpcServer |
<?php
/**
* file:HttpRpcServer.php
* This file is part of J-Game.
* @link https://www.liangboceo.com
* @document https://doc.liangboceo.com
* @contact 173120209@qq.com
* @autho:jackliang
*/
namespace f4engine\engine;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\Http\Server;
use Think\App;
use Think\Build;
use Think\Hook;
use Think\Route;
use Think\Storage;
use Think\Think;
class HttpRpcServer
{
private static $instance;
/**
* @return self
*/
public static function getInstance()
{
if (self::$instance == null) {
self::$instance = new self();
}
self::tp_start();
return self::$instance;
}
public function start()
{
$http = new \swoole_http_server("127.0.0.1", 9501);
$http->on("start", function (Server $server) {
Logger::debug("输出=====,服务启动中", $server->port);
});
$http->on("request", function (Request $request, Response $response) {
Logger::debug("输出=====", json_encode($request));
self::run($request, $response);
});
$http->start();
}
private static function tp_start()
{
spl_autoload_register('Think\Think::autoload');
// 设定错误和异常处理
register_shutdown_function('Think\Think::fatalError');
set_error_handler('Think\Think::appError');
set_exception_handler('Think\Think::appException');
// 初始化文件存储方式
Storage::connect(STORAGE_TYPE);
$runtimefile = RUNTIME_PATH . APP_MODE . '~runtime.php';
if (!APP_DEBUG && Storage::has($runtimefile)) {
Storage::load($runtimefile);
} else {
$content = '';
// 读取应用模式
$mode = include is_file(CONF_PATH . 'core.php') ? CONF_PATH . 'core.php' : MODE_PATH . APP_MODE . '.php';
// 加载核心文件
foreach ($mode['core'] as $file) {
if (is_file($file)) {
include $file;
if (!APP_DEBUG) {
$content .= compile($file);
}
}
}
// 加载应用模式配置文件
foreach ($mode['config'] as $key => $file) {
is_numeric($key) ? C(load_config($file)) : C($key, load_config($file));
}
// 读取当前应用模式对应的配置文件
if ('common' != APP_MODE && is_file(CONF_PATH . 'config_' . APP_MODE . CONF_EXT)) {
C(load_config(CONF_PATH . 'config_' . APP_MODE . CONF_EXT));
}
// 加载模式别名定义
if (isset($mode['alias'])) {
Think::addMap(is_array($mode['alias']) ? $mode['alias'] : include $mode['alias']);
}
// 加载应用别名定义文件
if (is_file(CONF_PATH . 'alias.php')) {
Think::addMap(include CONF_PATH . 'alias.php');
}
// 加载模式行为定义
if (isset($mode['tags'])) {
Hook::import(is_array($mode['tags']) ? $mode['tags'] : include $mode['tags']);
}
// 加载应用行为定义
if (is_file(CONF_PATH . 'tags.php')) // 允许应用增加开发模式配置定义
{
Hook::import(include CONF_PATH . 'tags.php');
}
// 加载框架底层语言包
L(include THINK_PATH . 'Lang/' . strtolower(C('DEFAULT_LANG')) . '.php');
if (!APP_DEBUG) {
$content .= "\nnamespace { Think\\Think::addMap(" . var_export(think::getMap(), true) . ");";
$content .= "\nL(" . var_export(L(), true) . ");\nC(" . var_export(C(), true) . ');Think\Hook::import(' . var_export(Hook::get(), true) . ');}';
Storage::put($runtimefile, strip_whitespace('<?php ' . $content));
} else {
// 调试模式加载系统默认的配置文件
C(include THINK_PATH . 'Conf/debug.php');
// 读取应用调试配置文件
if (is_file(CONF_PATH . 'debug' . CONF_EXT)) {
C(include CONF_PATH . 'debug' . CONF_EXT);
}
}
}
// 读取当前应用状态对应的配置文件
if (APP_STATUS && is_file(CONF_PATH . APP_STATUS . CONF_EXT)) {
C(include CONF_PATH . APP_STATUS . CONF_EXT);
}
// 设置系统时区
date_default_timezone_set(C('DEFAULT_TIMEZONE'));
// 检查应用目录结构 如果不存在则自动创建
if (C('CHECK_APP_DIR')) {
$module = defined('BIND_MODULE') ? BIND_MODULE : C('DEFAULT_MODULE');
if (!is_dir(APP_PATH . $module) || !is_dir(LOG_PATH)) {
// 检测应用目录结构
Build::checkDir($module);
}
}
// 记录加载文件时间
G('loadTime');
// 运行应用
}
private static function run(Request $request, Response $response)
{
// 加载动态应用公共文件和配置
load_ext_file(COMMON_PATH);
// 应用初始化标签
Hook::listen('app_init');
self::init($request);
// 应用开始标签
Hook::listen('app_begin');
// Session初始化
if (!IS_CLI) {
session(C('SESSION_OPTIONS'));
}
// 记录应用初始化时间
G('initTime');
self::exec($response);
// 应用结束标签
Hook::listen('app_end');
return;
}
/**
* 应用程序初始化
* @access public
* @return void
*/
private static function init(Request $request)
{
// 日志目录转换为绝对路径 默认情况下存储到公共模块下面
C('LOG_PATH', realpath(LOG_PATH) . '/Common/');
Logger::debug(json_encode($request->server));
// 定义当前请求的系统常量
define('NOW_TIME', $request->server['request_time']);
define('REQUEST_METHOD', $request->server['request_method']);
define('IS_GET', REQUEST_METHOD == 'GET' ? true : false);
define('IS_POST', REQUEST_METHOD == 'POST' ? true : false);
define('IS_PUT', REQUEST_METHOD == 'PUT' ? true : false);
define('IS_DELETE', REQUEST_METHOD == 'DELETE' ? true : false);
// URL调度
self::dispatch($request);
if (C('REQUEST_VARS_FILTER')) {
// 全局安全过滤
array_walk_recursive($request->get, 'think_filter');
array_walk_recursive($request->post, 'think_filter');
array_walk_recursive($request->request, 'think_filter');
}
// URL调度结束标签
Hook::listen('url_dispatch');
define('IS_AJAX', ((isset($request->server['HTTP_X_REQUESTED_WITH']) && strtolower($request->server['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') || !empty($request->post[C('VAR_AJAX_SUBMIT')]) || !empty($request->get[C('VAR_AJAX_SUBMIT')])) ? true : false);
// TMPL_EXCEPTION_FILE 改为绝对地址
C('TMPL_EXCEPTION_FILE', realpath(C('TMPL_EXCEPTION_FILE')));
return;
}
/**
* 执行应用程序
* @access public
* @return void
*/
private static function exec(Response $response)
{
if (!preg_match('/^[A-Za-z](\/|\w)*$/', CONTROLLER_NAME)) {
// 安全检测
$module = false;
} elseif (C('ACTION_BIND_CLASS')) {
// 操作绑定到类:模块\Controller\控制器\操作
$layer = C('DEFAULT_C_LAYER');
if (is_dir(MODULE_PATH . $layer . '/' . CONTROLLER_NAME)) {
$namespace = MODULE_NAME . '\\' . $layer . '\\' . CONTROLLER_NAME . '\\';
} else {
// 空控制器
$namespace = MODULE_NAME . '\\' . $layer . '\\_empty\\';
}
$actionName = strtolower(ACTION_NAME);
if (class_exists($namespace . $actionName)) {
$class = $namespace . $actionName;
} elseif (class_exists($namespace . '_empty')) {
// 空操作
$class = $namespace . '_empty';
} else {
E(L('_ERROR_ACTION_') . ':' . ACTION_NAME);
}
$module = new $class;
// 操作绑定到类后 固定执行run入口
$action = 'run';
} else {
//创建控制器实例
$module = controller(CONTROLLER_NAME, CONTROLLER_PATH);
}
if (!$module) {
if ('4e5e5d7364f443e28fbf0d3ae744a59a' == CONTROLLER_NAME) {
$response->header("Content-type", "image/png");
$response->end(base64_decode(App::logo()));
}
// 是否定义Empty控制器
$module = A('Empty');
if (!$module) {
E(L('_CONTROLLER_NOT_EXIST_') . ':' . CONTROLLER_NAME);
}
}
// 获取当前操作名 支持动态路由
if (!isset($action)) {
$action = ACTION_NAME . C('ACTION_SUFFIX');
}
try {
self::invokeAction($module, $action, $response);
} catch (\ReflectionException $e) {
// 方法调用发生异常后 引导到__call方法处理
$method = new \ReflectionMethod($module, '__call');
$response->end($method->invokeArgs($module, array($action, '')));
}
return;
}
private static function invokeAction($module, $action, Response $response)
{
if (!preg_match('/^[A-Za-z](\w)*$/', $action)) {
// 非法操作
throw new \ReflectionException();
}
//执行当前操作
$method = new \ReflectionMethod($module, $action);
if ($method->isPublic() && !$method->isStatic()) {
$class = new \ReflectionClass($module);
// 前置操作
if ($class->hasMethod('_before_' . $action)) {
$before = $class->getMethod('_before_' . $action);
if ($before->isPublic()) {
$before->invoke($module);
}
}
// URL参数绑定检测
if ($method->getNumberOfParameters() > 0 && C('URL_PARAMS_BIND')) {
switch ($_SERVER['REQUEST_METHOD']) {
case 'POST':
$vars = array_merge($_GET, $_POST);
break;
case 'PUT':
parse_str(file_get_contents('php://input'), $vars);
break;
default:
$vars = $_GET;
}
$params = $method->getParameters();
$paramsBindType = C('URL_PARAMS_BIND_TYPE');
foreach ($params as $param) {
$name = $param->getName();
if (1 == $paramsBindType && !empty($vars)) {
$args[] = array_shift($vars);
} elseif (0 == $paramsBindType && isset($vars[$name])) {
$args[] = $vars[$name];
} elseif ($param->isDefaultValueAvailable()) {
$args[] = $param->getDefaultValue();
} else {
E(L('_PARAM_ERROR_') . ':' . $name);
}
}
// 开启绑定参数过滤机制
if (C('URL_PARAMS_FILTER')) {
$filters = C('URL_PARAMS_FILTER_TYPE') ?: C('DEFAULT_FILTER');
if ($filters) {
$filters = explode(',', $filters);
foreach ($filters as $filter) {
$args = array_map_recursive($filter, $args); // 参数过滤
}
}
}
array_walk_recursive($args, 'think_filter');
$arg = $method->invokeArgs($module, $args);
if (is_array($arg)) {
if (isset($arg['header'])) {
foreach ($arg['header'] as $k => $v) {
$response->header($k, $v);
}
}
if (isset($arg['body'])) {
$response->end($arg['body']);
}
} else {
$response->end($arg);
}
} else {
$arg = $method->invoke($module);
if (is_array($arg)) {
if (isset($arg['header'])) {
foreach ($arg['header'] as $k => $v) {
$response->header($k, $v);
}
}
if (isset($arg['body'])) {
$response->end($arg['body']);
}
} else {
$response->end($arg);
}
}
// 后置操作
if ($class->hasMethod('_after_' . $action)) {
$after = $class->getMethod('_after_' . $action);
if ($after->isPublic()) {
$after->invoke($module);
}
}
} else {
// 操作方法不是Public 抛出异常
throw new \ReflectionException();
}
}
/**
* URL映射到控制器
* @access public
* @return void
*/
private static function dispatch(Request $request)
{
$varPath = C('VAR_PATHINFO');
$urlCase = C('URL_CASE_INSENSITIVE');
if (isset($request->get[$varPath])) { // 判断URL里面是否有兼容模式参数
$request->server['path_info'] = $request->get[$varPath];
unset($request->get[$varPath]);
}
// 开启子域名部署
if (C('APP_SUB_DOMAIN_DEPLOY')) {
$rules = C('APP_SUB_DOMAIN_RULES');
if (isset($rules[$request->server['http_host']])) { // 完整域名或者IP配置
define('APP_DOMAIN', $request->server['http_host']); // 当前完整域名
$rule = $rules[APP_DOMAIN];
} else {
if (strpos(C('APP_DOMAIN_SUFFIX'), '.')) { // com.cn net.cn
$domain = array_slice(explode('.', $request->server['http_host']), 0, -3);
} else {
$domain = array_slice(explode('.', $request->server['http_host']), 0, -2);
}
if (!empty($domain)) {
$subDomain = implode('.', $domain);
define('SUB_DOMAIN', $subDomain); // 当前完整子域名
$domain2 = array_pop($domain); // 二级域名
if ($domain) {
// 存在三级域名
$domain3 = array_pop($domain);
}
if (isset($rules[$subDomain])) {
// 子域名
$rule = $rules[$subDomain];
} elseif (isset($rules['*.' . $domain2]) && !empty($domain3)) {
// 泛三级域名
$rule = $rules['*.' . $domain2];
$panDomain = $domain3;
} elseif (isset($rules['*']) && !empty($domain2) && 'www' != $domain2) {
// 泛二级域名
$rule = $rules['*'];
$panDomain = $domain2;
}
}
}
if (!empty($rule)) {
// 子域名部署规则 '子域名'=>array('模块名[/控制器名]','var1=a&var2=b');
if (is_array($rule)) {
list($rule, $vars) = $rule;
}
$array = explode('/', $rule);
// 模块绑定
define('BIND_MODULE', array_shift($array));
// 控制器绑定
if (!empty($array)) {
$controller = array_shift($array);
if ($controller) {
define('BIND_CONTROLLER', $controller);
}
}
if (isset($vars)) {
// 传入参数
parse_str($vars, $parms);
if (isset($panDomain)) {
$pos = array_search('*', $parms);
if (false !== $pos) {
// 泛域名作为参数
$parms[$pos] = $panDomain;
}
}
$_GET = array_merge($_GET, $parms);
}
}
}
// 分析PATHINFO信息
if (!isset($request->server['path_info'])) {
$types = explode(',', C('URL_PATHINFO_FETCH'));
foreach ($types as $type) {
if (0 === strpos($type, ':')) {
// 支持函数判断
$request->server['path_info'] = call_user_func(substr($type, 1));
break;
} elseif (!empty($request->server[$type])) {
$request->server['path_info'] = (0 === strpos($request->server[$type], $request->server['SCRIPT_NAME'])) ?
substr($request->server[$type], strlen($request->server['SCRIPT_NAME'])) : $request->server[$type];
break;
}
}
}
$depr = C('URL_PATHINFO_DEPR');
define('MODULE_PATHINFO_DEPR', $depr);
if (empty($request->server['path_info'])) {
$_SERVER['PATH_INFO'] = '';
define('__INFO__', '');
define('__EXT__', '');
$paths = array();
} else {
// URL后缀
define('__EXT__', strtolower(pathinfo($request->server['path_info'], PATHINFO_EXTENSION)));
// 检查禁止访问的URL后缀
if ($denySuffix = C('URL_DENY_SUFFIX')) {
if (in_array(__EXT__, explode('|', strtolower(str_replace('.', '', $denySuffix))))) {
send_http_status(404);
exit;
}
}
define('__INFO__', trim($request->server['path_info'], '/'));
// 去除URL后缀
$request->server['path_info'] = preg_replace('/\.' . __EXT__ . '$/i', '', __INFO__);
$paths = explode($depr, trim($request->server['path_info'], $depr));
}
Logger::debug($request->server['path_info']);
// URL常量
define('__SELF__', strip_tags($_SERVER[C('URL_REQUEST_URI')]));
// 获取模块名称
define('MODULE_NAME', self::getModule($paths));
// 检测模块是否存在
if (MODULE_NAME && is_dir(APP_PATH . MODULE_NAME)) {
// 定义当前模块路径
define('MODULE_PATH', APP_PATH . MODULE_NAME . '/');
// 定义当前模块的模版缓存路径
C('CACHE_PATH', CACHE_PATH . MODULE_NAME . '/');
// 定义当前模块的日志目录
C('LOG_PATH', realpath(LOG_PATH) . '/' . MODULE_NAME . '/');
// 模块配置文件开始载入检测位
Hook::listen('module_check');
// 加载模块配置文件
if (is_file(MODULE_PATH . 'Conf/config' . CONF_EXT)) {
C(load_config(MODULE_PATH . 'Conf/config' . CONF_EXT));
}
// 加载应用模式对应的配置文件
if ('common' != APP_MODE && is_file(MODULE_PATH . 'Conf/config_' . APP_MODE . CONF_EXT)) {
C(load_config(MODULE_PATH . 'Conf/config_' . APP_MODE . CONF_EXT));
}
// 当前应用状态对应的配置文件
if (APP_STATUS && is_file(MODULE_PATH . 'Conf/' . APP_STATUS . CONF_EXT)) {
C(load_config(MODULE_PATH . 'Conf/' . APP_STATUS . CONF_EXT));
}
// 加载模块别名定义
if (is_file(MODULE_PATH . 'Conf/alias.php')) {
Think::addMap(include MODULE_PATH . 'Conf/alias.php');
}
// 加载模块tags文件定义
if (is_file(MODULE_PATH . 'Conf/tags.php')) {
Hook::import(include MODULE_PATH . 'Conf/tags.php');
}
// 加载模块函数文件
if (is_file(MODULE_PATH . 'Common/function.php'))
include MODULE_PATH . 'Common/function.php';
// 加载模块的扩展配置文件
load_ext_file(MODULE_PATH);
// 模块配置文件加载完成检测位
Hook::listen('module_config');
} else {
E(L('_MODULE_NOT_EXIST_') . ':' . MODULE_NAME);
}
if (!defined('__APP__')) {
$urlMode = C('URL_MODEL');
if (URL_COMPAT == $urlMode) {
// 兼容模式判断
define('PHP_FILE', _PHP_FILE_ . '?' . $varPath . '=');
} elseif (URL_REWRITE == $urlMode) {
$url = dirname(_PHP_FILE_);
if ('/' == $url || '\\' == $url) {
$url = '';
}
define('PHP_FILE', $url);
} else {
define('PHP_FILE', _PHP_FILE_);
}
// 当前应用地址
define('__APP__', strip_tags(PHP_FILE));
}
// 模块URL地址
$moduleName = defined('MODULE_ALIAS') ? MODULE_ALIAS : MODULE_NAME;
define('__MODULE__', (defined('BIND_MODULE') || !C('MULTI_MODULE')) ? __APP__ : __APP__ . '/' . ($urlCase ? strtolower($moduleName) : $moduleName));
// 获取控制器和操作名
define('CONTROLLER_NAME', self::getController($paths, $urlCase));
define('ACTION_NAME', self::getAction($paths, $urlCase));
if ($paths) {
// 解析剩余的URL参数
$var = array();
if (C('URL_PARAMS_BIND') && 1 == C('URL_PARAMS_BIND_TYPE')) {
// URL参数按顺序绑定变量
$var = $paths;
} else {
preg_replace_callback('/(\w+)\/([^\/]+)/', function ($match) use (&$var) {
$var[$match[1]] = strip_tags($match[2]);
}, implode('/', $paths));
}
$_GET = array_merge($var, $_GET);
}
// 获取控制器的命名空间(路径)
define('CONTROLLER_PATH', self::getSpace($urlCase));
// 当前控制器的UR地址
$controllerName = defined('CONTROLLER_ALIAS') ? CONTROLLER_ALIAS : CONTROLLER_NAME;
define('__CONTROLLER__', __MODULE__ . $depr . (defined('BIND_CONTROLLER') ? '' : ($urlCase ? parse_name($controllerName) : $controllerName)));
// 当前操作的URL地址
define('__ACTION__', __CONTROLLER__ . $depr . (defined('ACTION_ALIAS') ? ACTION_ALIAS : ACTION_NAME));
//保证$_REQUEST正常取值
$_REQUEST = array_merge($_POST, $_GET);
}
/**
* 获得控制器的命名空间路径 便于插件机制访问
* @param boolean $urlCase 是否转换成小写
* @return string
*/
private static function getSpace($urlCase)
{
$var = C('VAR_ADDON');
$space = !empty($_GET[$var]) ? strip_tags($_GET[$var]) : '';
unset($_GET[$var]);
return $space;
}
/**
* 获得实际的控制器名称
* @param array $paths path_info数组
* @param boolean $urlCase 是否转换成小写
* @return string
*/
private static function getController(&$paths, $urlCase)
{
if (defined('BIND_CONTROLLER')) {
return BIND_CONTROLLER;
} else {
if ($paths && C('URL_ROUTER_ON') && Route::check($paths)) {
$depr = C('URL_PATHINFO_DEPR');
$paths = explode($depr, trim($_SERVER['PATH_INFO'], $depr));
}
if ($paths) {
// PATH_INFO检测标签位
Hook::listen('path_info');
if (C('CONTROLLER_LEVEL') > 1) {// 控制器层次
$controller = implode('/', array_slice($paths, 0, C('CONTROLLER_LEVEL')));
$paths = array_slice($paths, C('CONTROLLER_LEVEL'));
} else {
$controller = array_shift($paths);
}
} else {
$var = C('VAR_CONTROLLER');
if (!empty($_GET[$var])) {
$controller = $_GET[$var];
unset($_GET[$var]);
} else {
$controller = C('DEFAULT_CONTROLLER');
}
}
}
if ($maps = C('URL_CONTROLLER_MAP')) {
if (isset($maps[strtolower($controller)])) {
// 记录当前别名
define('CONTROLLER_ALIAS', strtolower($controller));
// 获取实际的控制器名
return ucfirst($maps[CONTROLLER_ALIAS]);
} elseif (array_search(strtolower($controller), $maps)) {
// 禁止访问原始控制器
return '';
}
}
if ($urlCase) {
// URL地址不区分大小写
// 智能识别方式 user_type 识别到 UserTypeController 控制器
$controller = parse_name($controller, 1);
}
return strip_tags(ucfirst($controller));
}
/**
* 获得实际的操作名称
* @param array $paths path_info数组
* @param boolean $urlCase 是否转换成小写
* @return string
*/
private static function getAction(&$paths, $urlCase)
{
if (defined('BIND_ACTION')) {
return BIND_ACTION;
} else {
if ($paths) {
$action = array_shift($paths);
} else {
$var = C('VAR_ACTION');
if (!empty($_GET[$var])) {
$action = $_GET[$var];
unset($_GET[$var]);
} elseif (!empty($_POST[$var])) {
$action = $_POST[$var];
unset($_POST[$var]);
} else {
$action = C('DEFAULT_ACTION');
}
}
}
if ($maps = C('URL_ACTION_MAP')) {
if (isset($maps[strtolower(CONTROLLER_NAME)])) {
$maps = $maps[strtolower(CONTROLLER_NAME)];
if (isset($maps[strtolower($action)])) {
// 记录当前别名
define('ACTION_ALIAS', strtolower($action));
// 获取实际的操作名
if (is_array($maps[ACTION_ALIAS])) {
parse_str($maps[ACTION_ALIAS][1], $vars);
$_GET = array_merge($_GET, $vars);
return $maps[ACTION_ALIAS][0];
} else {
return $maps[ACTION_ALIAS];
}
} elseif (array_search(strtolower($action), $maps)) {
// 禁止访问原始操作
return '';
}
}
}
return strip_tags($urlCase ? strtolower($action) : $action);
}
/**
* 获得实际的模块名称
* @param array $paths path_info数组
* @return string
*/
private static function getModule(&$paths)
{
if (defined('BIND_MODULE')) {
return BIND_MODULE;
} else {
// 检查路由
if ($paths && C('URL_ROUTER_ON') && Route::check($paths)) {
$paths = explode(MODULE_PATHINFO_DEPR, trim($_SERVER['PATH_INFO'], MODULE_PATHINFO_DEPR));
}
if ($paths && C('MULTI_MODULE')) { // 获取模块名
$allowList = C('MODULE_ALLOW_LIST'); // 允许的模块列表
if (empty($allowList) || (is_array($allowList) && in_array_case($paths[0], $allowList))) {
$module = array_shift($paths);
$_SERVER['PATH_INFO'] = implode(MODULE_PATHINFO_DEPR, $paths);
}
} else {
$var = C('VAR_MODULE');
if (!empty($_GET[$var])) {
$module = $_GET[$var];
unset($_GET[$var]);
}
}
if (empty($module)) {
$module = C('DEFAULT_MODULE');
}
}
if ($maps = C('URL_MODULE_MAP')) {
if (isset($maps[strtolower($module)])) {
// 记录当前别名
define('MODULE_ALIAS', strtolower($module));
// 获取实际的模块名
return ucfirst($maps[MODULE_ALIAS]);
} elseif (array_search(strtolower($module), $maps) || in_array_case($module, C('MODULE_DENY_LIST'))) {
// 禁止访问原始模块
return '';
}
}
return strip_tags(ucfirst($module));
}
}