123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- <?php
- namespace loyalsoft;
- /**
- * 服务端程序入口(单一入口)
- * method: post/get 皆可
- * params: 一个经过(压缩)转码的json串.
- * @author gwang (mail@wanggangzero.cn)
- * @version 2018.11.08
- * @modifys
- * 2018.11.08 将index.php原来的代码整理到Index类中,使用到的全局变量用类的静态变量打理起来。
- * 给$req的全局静态变量增加req()访问方式。
- * 对于逻辑中的ErrResp, 添加Err方法,直接截断逻辑,返回响应结果。 -- gwang
- * 2018.04.05 去掉返回值中的content-encoding信息,开发了配套的fiddler插件,不需要自动识别机制了. --gwang
- * 2017.11.15 调整传输层协议, get的返回值也采用deflate编码.
- * 2017.07.19 代码优化, 格式整理
- * 2016.4.26 引入客户端检查机制,来源为模拟客户端时输出调试信息.
- * 2016.4.25 echo 中的连字符改为逗号表达式.
- */
- class Index {
- /**
- * @var boolean 请求方式是否为Post
- */
- static $isPost = false;
- /**
- * @var string 调试信息
- */
- static $debugMsg = "";
- /**
- * @var string user-agent
- */
- static $ua = "";
- /**
- * @var boolean 调试模式
- */
- static $isDebugging = false;
- /**
- * @var int 超大响应的判断标准50kb
- */
- static $bigRespInKbs = 50;
- static function Init() {
- ob_start(); # 开启一重output_buffer截获意外输出.
- self::$isPost = (isset($_SERVER['REQUEST_METHOD']) ? ($_SERVER['REQUEST_METHOD'] == 'PUT' || $_SERVER['REQUEST_METHOD'] == 'POST' ) : FALSE); # 判断是否为Post方式
- self::$debugMsg = ""; # 记录调试信息
- self::$ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; # 客户端标志
- self::$isDebugging = isset(self::$ua) && \strncmp(self::$ua, "WebRequest", 10) == 0; # 是否将ob_buff的输出信息附加到返回值
- self::$bigRespInKbs = self::$isDebugging ? 1 : 50; # 记录超大返回值,测试模式1k,正式50k.
- include_once __DIR__ . '/Services/AppServer.php'; # 引入主程序
- $data = query_string(); # 取参数
- if (self::$isDebugging) { # 调试模式=>性能记录
- $rt = new RenderTime(); # 计时器, 默认开始计时
- }
- # 传输层解码(压缩、去除控制字符)
- # 目前规则: Post发送数据时使用deflate编码, GET方式发送数据时使用base64编码
- $data = self::$isPost ? gzinflate($data) : base64_decode($data);
- //$data = base64_decode($data);
- # 加密层解码, 加密传输, 保障数据安全
- # ....
- $req = JsonUtil::decode($data); # 请求数据, 数据层协议JSON
- if (self::$isDebugging) { # 刷调试信息
- $rt->end(); # 计时器结束
- self::$debugMsg .= '<br/>解压耗时:' . $rt->getRenderTime(); # 解码耗时
- # 计时器开始
- }
- new Req($req); # 初始化req()
- }
- static function Run() {
- if (self::$isDebugging) { # 调试模式=>性能记录
- $rt = new RenderTime(); # 计时器, 默认开始计时
- $rt->start();
- }
- $app = new AppServer(); # 初始化业务框架
- $resp = $app->api(); # 分发处理逻辑
- if (self::$isDebugging) { # 组织调试信息
- $rt->end(); # 计时器结束
- $ms = round($rt->getRenderTime(false) / 1000, 2); # 耗时换算成毫秒
- $msi = $ms > 50 ? "<font color='red'>$ms</font>" : $ms; # 超过50ms用红色显示
- self::$debugMsg .= "<br/>逻辑耗时: $msi 毫秒"; # 逻辑耗时
- self::$debugMsg .= '<br/>内存分配:' . number_format(memory_get_peak_usage() / 1024) . 'kb,';
- self::$debugMsg .= '内存占用:' . number_format(memory_get_usage() / 1024) . 'kb'; # 内存使用数量(kb)
- }
- return $resp;
- }
- static function OverPass($resp) {
- $ret = JsonUtil::encode($resp); # 返回值, 数据层协议:JSON
- $errinfo = ob_get_clean(); # 检查并截获异常输出
- if (self::$isDebugging) { # 附加调试信息和异常输出
- $ret .= '<br/><hr/><font color=\'#6666FF\'>' . self::$debugMsg; # 附加调试信息,
- if (strlen($errinfo) > 0) { # 将捕获的异常输出附加到返回值
- $ret .= '<br/><br/>Unexpected output:<br/>' . $errinfo;
- }
- $ret .= '</font>';
- } else {
- if (!empty(self::$debugMsg)) {
- CLog::err(self::$debugMsg);
- }
- }
- # 返回数据, 加密层编码, 加密传输, 保障数据安全
- # ....
- # 返回数据, 传输层编码(一律deflate压缩)
- if (php_sapi_name() === 'cli') {
- # 命令行的就算了, 要不肉眼看不懂了
- } else {
- $ret = gzdeflate($ret); # 不管请求时使用的是什么方法, 返回时一律使用deflate压缩
- }
- $retLen = strlen($ret); # 计算下返回值长度.
- if ($retLen > (1024 * self::$bigRespInKbs)) { # 长度大于50k时记录超大返回值日志.
- CLog::warn("Big Response(" . req()->cmd . "):\n" # 带有\n转义符的时候, 必须用双引号
- . "\t" . substr(JsonUtil::encode($resp), 0, 30) # 返回串(截断为30bytes)
- . "..., about " . CommUtil::floatToInt($retLen / 1024) . "kbs.", "Index"); # 返回串长度
- }
- return $ret;
- }
- /**
- * 直接返回错误resp并结束运行
- * @param int $err
- * @param string $msg
- */
- static function Err($err, $msg = "") {
- if (ErrCode::ok === $err) {
- CLog::err("Err()方法的参数err==ok, 那你还调个蛋的Err()!!!");
- }
- if (Index::$isDebugging) { # 组织调试信息
- Index::$debugMsg .= "<br/><font color='red'>发生错误逻辑中断($err):$msg</font>"; # 错误信息用红色显示
- Index::$debugMsg .= '<br/>内存分配:' . number_format(memory_get_peak_usage() / 1024) . 'kb,';
- Index::$debugMsg .= '内存占用:' . number_format(memory_get_usage() / 1024) . 'kb'; # 内存使用数量(kb)
- }
- if (is_string($err)) { # 防御Err中直接输入字符串的货
- $msg = "发生错误($err)直接中断逻辑执行." . $msg;
- CLog::err($msg);
- $err = ErrCode::err_innerfault;
- }
- $resp = Resp::err($err, $msg);
- $resp->AfterProc();
- exit(Index::OverPass($resp)); # 直接返回错误信息
- }
- }
- Index::Init();
- $resp = Index::Run();
- exit(Index::OverPass($resp));
|