/** * 实现register_shutdown_function */ public static function applyShutdownFunction() { Base::getLog()->debug(__METHOD__ . ' apply shutdown functions'); foreach (self::$shutdownFunctions as $pair) { call_user_func_array(Arr::get($pair, 'callback'), Arr::get($pair, 'params')); } }
/** * @inheritdoc */ public function executeAction() { // 继续执行 parent::executeAction(); Base::getLog()->debug(__METHOD__ . ' render json content type', ['type' => $this->contentType]); $this->response->headers('content-type', $this->contentType); $this->response->body = json_encode($this->actionResult); }
/** * 完成模板渲染,并输出 */ public function after() { if ($this->autoRender) { Base::getLog()->debug(__METHOD__ . ' render template view'); $this->response->body = $this->template->render(); } parent::after(); }
/** * 每个请求层,最终被调用的方法 * * @return mixed */ public function handle() { Base::getLog()->debug(__METHOD__ . ' handle main flow - start'); if (!Route::exists('default')) { Base::getLog()->debug(__METHOD__ . ' set default route'); Route::set('default', '(<controller>(/<action>(/<id>)))')->defaults(['controller' => 'Site', 'action' => 'index']); } $this->flow->contexts['uri'] = Url::detectUri(); Base::getLog()->debug(__METHOD__ . ' handle main flow - end'); }
/** * @inheritdoc */ public function destroy() { // 清空session数据 $_SESSION = []; Base::getLog()->debug(__METHOD__ . ' clean $_SESSION'); // 删除对应的session文件 $sessionID = HttpProtocol::getSessionID(); $file = HttpProtocol::getSessionFile($sessionID); FileHelper::delete($file); Base::getLog()->debug(__METHOD__ . ' delete session file', ['file' => $file]); }
/** * {@inheritdoc} */ public function prepareActionList() { $actions = parent::prepareActionList(); Base::getLog()->debug(__METHOD__ . ' handle rest controller request', ['method' => $this->request->method]); if (isset($this->methodMapping[$this->request->method])) { $action = $this->methodMapping[$this->request->method]; Base::getLog()->debug(__METHOD__ . ' found rest action', ['method' => $this->request->method, 'action' => $action]); $actions[] = $action; } Base::getLog()->debug(__METHOD__ . ' generate final rest action list', ['actions' => $actions]); return $actions; }
/** * @inheritdoc */ public function executeAction() { if (!($callback = $this->request->query($this->callbackParam)) && !$this->autoSink) { throw new JsonpInvalidParameterException('The required parameter ":param" not found.', [':param' => $this->callbackParam]); } // 继续执行 parent::executeAction(); // 附加上callback if ($callback) { Base::getLog()->debug(__METHOD__ . ' append callback string', ['callback' => $callback]); $this->response->body = $callback . '(' . $this->response->body . ')'; } }
/** * 每个请求层,最终被调用的方法 * * @return mixed */ public function handle() { Base::getLog()->debug(__METHOD__ . ' handle request flow - start'); $request = new Request($this->flow->contexts['uri']); // 上下文 $this->flow->contexts['request'] = $request; // 处理HTTP相关,例如过滤变量,初始化相关设置 $flow = Flow::instance('tourze-http'); $flow->contexts =& $this->flow->contexts; $flow->layers = ['tourze\\Bootstrap\\Flow\\Http\\Initialization', 'tourze\\Bootstrap\\Flow\\Http\\Authentication', 'tourze\\Bootstrap\\Flow\\Http\\Authorization']; $flow->start(); // 执行请求 $response = $request->execute(); echo $response->sendHeaders(true)->body; Base::getLog()->debug(__METHOD__ . ' handle request flow - end'); }
/** * 处理请求统计 * * @param ConnectionInterface $connection * @param string $data * @return bool|void */ public function onMessage($connection, $data) { Base::getLog()->info(__METHOD__ . ' handle message', $data); $data = json_decode($data, true); if (empty($data) || !isset($data['cmd'])) { Base::getLog()->info(__METHOD__ . ' no cmd param, or the data format is wrong', $data); return false; } // 无法解析的包 if (empty($data['cmd']) || $data['cmd'] != 'REPORT_IP') { return false; } Base::getLog()->info(__METHOD__ . ' response ok'); /** @var \Workerman\Connection\ConnectionInterface $connection */ return $connection->send(json_encode(['result' => 'ok'])); }
/** * {@inheritdoc} */ protected function capture($viewFilename, array $viewData) { TourzeBase::getLog()->debug(__METHOD__ . ' capture view output', ['file' => $viewFilename]); // 导入变量 extract($viewData, EXTR_SKIP); if (!empty(View::$_globalData)) { extract(View::$_globalData, EXTR_SKIP | EXTR_REFS); } ob_start(); try { include $viewFilename; } catch (Exception $e) { ob_end_clean(); throw $e; } // 获取最终内容 return ob_get_clean(); }
/** * 处理请求 * * $request->execute(); * * @param Request $request * @param Response $response * @return \tourze\Http\Response * @throws \tourze\Base\Exception\BaseException */ public function executeRequest(Request $request, Response $response) { $className = 'Controller'; // 控制器 $controller = $request->controller; $className = Inflector::classify($controller) . $className; // 目录 $directory = $request->directory; if ($directory) { $directory = str_replace('/', '\\', $directory); $className = $directory . $className; } // 保存请求状态 $previous = Request::$current; Request::$current = $request; Base::getLog()->info(__METHOD__ . ' controller class', ['class' => $className]); try { if (!class_exists($className)) { Base::getLog()->debug(__METHOD__ . ' class not found', ['class' => $className]); throw HttpException::factory(Http::NOT_FOUND, 'The requested URL :uri was not found on this server.', [':uri' => $request->uri])->request($request); } $class = new ReflectionClass($className); if ($class->isAbstract()) { Base::getLog()->error(__METHOD__ . ' calling abstract controller class', ['class' => $className]); throw new BaseException('Cannot create instances of abstract :controller', [':controller' => $className]); } $controller = $class->newInstance(['request' => $request, 'response' => $response]); $response = $class->getMethod('execute')->invoke($controller); if (!$response instanceof Response) { Base::getLog()->error(__METHOD__ . ' unknown response type'); throw new BaseException('Controller failed to return a Response'); } } catch (HttpException $e) { if (null === $e->request()) { $e->request($request); } $response = $e->getResponse(); } Request::$current = $previous; return $response; }
public function getStasticLog($module, $interface, $startTime, $endTime, $count = 10) { $ipList = !empty($_GET['ip']) && is_array($_GET['ip']) ? $_GET['ip'] : Cache::$serverIpList; $offsetList = !empty($_GET['offset']) && is_array($_GET['offset']) ? $_GET['offset'] : []; $port = Config::load('statServer')->get('providerPort'); $requestBufferArray = []; foreach ($ipList as $key => $ip) { $offset = isset($offsetList[$key]) ? $offsetList[$key] : 0; $buffer = ['cmd' => 'get-log', 'module' => $module, 'interface' => $interface, 'start_time' => $startTime, 'end_time' => $endTime, 'offset' => $offset, 'count' => $count]; Base::getLog()->info(__METHOD__ . ' generate buffer fot getting log', $buffer); $requestBufferArray["{$ip}:{$port}"] = json_encode($buffer) . "\n"; } $readBufferArray = StatServer::multiRequest($requestBufferArray); ksort($readBufferArray); foreach ($readBufferArray as $address => $buf) { $bodyData = json_decode(trim($buf), true); $logData = isset($bodyData['data']) ? $bodyData['data'] : ''; $offset = isset($bodyData['offset']) ? $bodyData['offset'] : 0; $readBufferArray[$address] = ['offset' => $offset, 'data' => $logData]; } return $readBufferArray; }
/** * 上报统计数据 * * @param string $module * @param string $interface * @param bool $success * @param int $code * @param string $msg * @param string $reportAddress * @return boolean */ public static function report($module, $interface, $success, $code, $msg, $reportAddress = '') { // 如果msg是个数组,那么要额外处理转换成字符串 if (is_array($msg)) { // $msg格式为[':message', [':message' => 'TEST']] if (count($msg) == 2 && !Arr::isAssoc($msg) && is_array($msg[1])) { $msg = __($msg[0], $msg[1]); } } if (strpos($msg, '[ip]') !== false) { $msg = str_replace('[ip]', Arr::get($_SERVER, 'REMOTE_ADDR'), $msg); } if (strpos($msg, '[ua]') !== false) { $msg = str_replace('[ua]', Arr::get($_SERVER, 'HTTP_USER_AGENT'), $msg); } $reportAddress = $reportAddress ? $reportAddress : Config::load('statClient')->get('ip'); if (isset(self::$timeMap[$module][$interface]) && self::$timeMap[$module][$interface] > 0) { $startTime = self::$timeMap[$module][$interface]; self::$timeMap[$module][$interface] = 0; } else { if (isset(self::$timeMap['']['']) && self::$timeMap[''][''] > 0) { $startTime = self::$timeMap['']['']; self::$timeMap[''][''] = 0; } else { $startTime = microtime(true); } } //echo "\n"; //echo $startTime . "\n"; $endTime = microtime(true); //echo $endTime . "\n"; $costTime = $endTime - $startTime; //echo $costTime . "\n"; $binData = Protocol::encode($module, $interface, $costTime, $success, $code, $msg); Base::getLog()->debug(__METHOD__ . ' prepare bin data', ['bin' => $binData]); return self::sendData($reportAddress, $binData); }
/** * 单例模式,获取一个指定的实例 * * // 加载默认实例 * $db = Database::instance(); * * // 指定实例名称和配置 * $db = Database::instance('custom', $config); * * @param string $name 实例名 * @param array $config 配置参数 * @return Connection */ public static function instance($name = null, array $config = null) { if (null === $name) { $name = Db::$default; } if (!isset(Db::$instances[$name])) { // 读取配置 if (null === $config) { $config = (array) Config::load(self::$configFile)->get($name); Base::getLog()->debug(__METHOD__ . ' get default config', ['name' => $name]); } // 合并默认配置 if (isset(self::$defaultConfig[Arr::get($config, 'driver')])) { $config = Arr::merge(self::$defaultConfig[Arr::get($config, 'driver')], $config); Base::getLog()->debug(__METHOD__ . ' merge config', ['name' => $name]); } $conn = DriverManager::getConnection($config); Base::getLog()->debug(__METHOD__ . ' create dbal connection', ['name' => $name]); // 额外注册字段类型 if (isset(self::$mappingType[Arr::get($config, 'driver')])) { $platform = $conn->getDatabasePlatform(); foreach (self::$mappingType[Arr::get($config, 'driver')] as $dbType => $doctrineType) { if (!$platform->hasDoctrineTypeMappingFor($dbType)) { Base::getLog()->debug(__METHOD__ . ' add dbal mapping type', ['raw' => $dbType, 'dbal' => $doctrineType]); $platform->registerDoctrineTypeMapping($dbType, $doctrineType); } } } Db::$instances[$name] = $conn; Base::getLog()->debug(__METHOD__ . ' save db instance', ['name' => $name]); } return Db::$instances[$name]; }
/** * 跳转的助手方法 * * @param string $uri 要跳转的URI * @param int $code HTTP状态码 * @throws HttpException */ public function redirect($uri = '', $code = 302) { Base::getLog()->debug(__METHOD__ . ' redirect from controller', ['uri' => $uri, 'code' => $code]); Base::getHttp()->redirect((string) $uri, $code); }
/** * 删除当前记录 * * @throws ModelException * @return Model */ public function delete() { if (!$this->_loaded) { throw new ModelException('Cannot delete :model model because it is not loaded.', [':model' => $this->_objectName]); } Base::getLog()->debug(__METHOD__ . ' delete record'); $id = $this->pk(); $this->_db->createQueryBuilder()->delete($this->_tableName)->where($this->_primaryKey . ' = ?')->setParameter(0, $id)->execute(); return $this->clear(); }
/** * 格式化日志记录 * * @param string $str * @param string $date * @param array $codeMap * @return array */ public static function formatStatLog($str, $date, &$codeMap) { Base::getLog()->info(__METHOD__ . ' format stat log', ['str' => $str, 'date' => $date]); // time:[success_count:xx,success_cost_time:xx,fail_count:xx,fail_cost_time:xx] $stData = $codeMap = []; $lines = explode("\n", $str); // 汇总计算 foreach ($lines as $line) { // line = IP time success_count success_cost_time fail_count fail_cost_time code_json $lineData = explode("\t", $line); if (!isset($lineData[5])) { continue; } $timeLine = Arr::get($lineData, 1); $timeLine = intval(ceil($timeLine / 300) * 300); $successCount = Arr::get($lineData, 2); $successCostTime = Arr::get($lineData, 3); $failCount = Arr::get($lineData, 4); $failCostTime = Arr::get($lineData, 5); $codeMapList = json_decode($lineData[6], true); if (!isset($stData[$timeLine])) { $stData[$timeLine] = ['success_count' => 0, 'success_cost_time' => 0, 'fail_count' => 0, 'fail_cost_time' => 0]; } $stData[$timeLine]['success_count'] += $successCount; $stData[$timeLine]['success_cost_time'] += $successCostTime; $stData[$timeLine]['fail_count'] += $failCount; $stData[$timeLine]['fail_cost_time'] += $failCostTime; if (is_array($codeMapList)) { foreach ($codeMapList as $code => $count) { if (!isset($codeMap[$code])) { $codeMap[$code] = 0; } $codeMap[$code] += $count; } } } // 按照时间排序 ksort($stData); // time => [total_count:xx,success_count:xx,suc_avg_time:xx,fail_count:xx,fail_avg_time:xx,percent:xx] $data = []; // 计算成功率 耗时 foreach ($stData as $timeLine => $item) { $data[$timeLine] = ['time' => date('Y-m-d H:i:s', $timeLine), 'total_count' => $item['success_count'] + $item['fail_count'], 'total_avg_time' => $item['success_count'] + $item['fail_count'] == 0 ? 0 : round(($item['success_cost_time'] + $item['fail_cost_time']) / ($item['success_count'] + $item['fail_count']), 6), 'success_count' => $item['success_count'], 'suc_avg_time' => $item['success_count'] == 0 ? $item['success_count'] : round($item['success_cost_time'] / $item['success_count'], 6), 'fail_count' => $item['fail_count'], 'fail_avg_time' => $item['fail_count'] == 0 ? 0 : round($item['fail_cost_time'] / $item['fail_count'], 6), 'percent' => $item['success_count'] + $item['fail_count'] == 0 ? 0 : round($item['success_count'] * 100 / ($item['success_count'] + $item['fail_count']), 4)]; } $timePoint = strtotime($date); for ($i = 0; $i < 288; $i++) { $data[$timePoint] = isset($data[$timePoint]) ? $data[$timePoint] : ['time' => date('Y-m-d H:i:s', $timePoint), 'total_count' => 0, 'total_avg_time' => 0, 'success_count' => 0, 'suc_avg_time' => 0, 'fail_count' => 0, 'fail_avg_time' => 0, 'percent' => 100]; $timePoint += 300; } ksort($data); return $data; }
/** * {@inheritdoc} */ public function destroy() { Base::getLog()->debug(__METHOD__ . ' destroy session'); return session_destroy(); }
/** * {@inheritdoc} */ public function send($from = null, $to = null, $subject = null, $message = null) { Base::getLog()->debug(__METHOD__ . ' call send mail method', ['to' => $to, 'subject' => $subject, 'message' => $message, 'from' => $from]); if ($to === null) { $to = $this->to; } if ($subject === null) { $subject = $this->subject; } if ($message === null) { $message = $this->message; } if ($from === null) { $from = $this->from; } if (is_array($to)) { $to = implode(', ', $to); } Base::getLog()->debug(__METHOD__ . ' prepare to send mail', ['to' => $to, 'subject' => $subject, 'message' => $message, 'from' => $from]); $result = @mail($to, $subject, $message, 'From: ' . $from); Base::getLog()->debug(__METHOD__ . ' send mail result', ['result' => $result]); $this->to = null; $this->subject = null; $this->message = null; $this->from = null; return $result; }
/** * 传入参数,生成当前路由的uri * * @param array $params URI参数 * @return string * @throws RouteException */ public function uri(array $params = null) { $defaults = $this->_defaults; if (isset($params['controller'])) { $params['controller'] = strtolower($params['controller']); } if (isset($params['directory'])) { $params['directory'] = strtolower($params['directory']); } /** * 匿名函数,用于循环替换路由参数 * * @param string $portion URI定义部分 * @param boolean $required 参数是否必须的 * @return array 返回保存参数的数组 * @throws RouteException */ $compile = function ($portion, $required) use(&$compile, $defaults, $params) { $missing = []; $pattern = '#(?:' . Route::REGEX_KEY . '|' . Route::REGEX_GROUP . ')#'; $result = preg_replace_callback($pattern, function ($matches) use(&$compile, $defaults, &$missing, $params, &$required) { if ('<' === $matches[0][0]) { $param = $matches[1]; if (isset($params[$param])) { $required = $required || !isset($defaults[$param]) || $params[$param] !== $defaults[$param]; return $params[$param]; } // 直接返回参数默认值 if (isset($defaults[$param])) { return $defaults[$param]; } $missing[] = $param; } else { $result = $compile($matches[2], false); if ($result[1]) { $required = true; return $result[0]; } } return null; }, $portion); if ($required && $missing) { throw new RouteException('Required route parameter not passed: :param', [':param' => reset($missing)]); } return [$result, $required]; }; $result = $compile($this->_uri, true); Base::getLog()->debug(__METHOD__ . ' get route compile result', ['identify' => $this->identify, 'result' => $result]); $uri = $result ? array_shift($result) : $result; // 过滤URI中的重复斜杆 $uri = preg_replace('#//+#', '/', rtrim($uri, '/')); // 如果是外部链接 if ($this->isExternal()) { $host = $this->_defaults['host']; // 使用默认协议 if (false === strpos($host, '://')) { $host = Route::$defaultProtocol . $host; } $uri = rtrim($host, '/') . '/' . $uri; } return $uri; }
/** * 解析HTTP_RANGE * * @return array|false */ protected function _parseByteRange() { if ($httpRange = Arr::get($_SERVER, 'HTTP_RANGE')) { Base::getLog()->debug(__METHOD__ . ' get HTTP_RANGE', ['string' => $httpRange]); preg_match_all('/(-?[0-9]++(?:-(?![0-9]++))?)(?:-?([0-9]++))?/', $httpRange, $matches, PREG_SET_ORDER); return $matches[0]; } else { return false; } }
/** * 记录异常信息 * * @param Exception $e */ public static function log(Exception $e) { Base::getLog()->error($e->getMessage(), ['code' => $e->getCode(), 'file' => $e->getFile(), 'line' => $e->getLine()]); }
/** * {@inheritdoc} */ public function headersSent(&$file = null, &$line = null) { Base::getLog()->debug(__METHOD__ . ' check if header sent', ['file' => $file, 'line' => $line]); return headers_sent($file, $line); }
/** * 获取指定的路由信息 * * $route = Route::get('default'); * * @param string $name 路由名称 * @return Entry * @throws BaseException */ public static function get($name) { if (!isset(Route::$routeInstances[$name])) { Base::getLog()->error(__METHOD__ . ' getting unknown route', ['name' => $name, 'exists' => array_keys(self::$routeInstances)]); throw new RouteNotFoundException('The requested route does not exist: :route', [':route' => $name]); } return Route::$routeInstances[$name]; }
/** * {@inheritdoc} */ public function remove($name) { Base::getLog()->debug(__METHOD__ . ' remove cache', ['name' => $name]); unset($this->_cache[$name]); unset($this->_cacheHit[$name]); return true; }
/** * 执行请求 * * @return Response * @throws HttpException * @throws ClientRecursionException * @throws RequestException */ public function execute() { if (!$this->external) { Base::getLog()->debug(__METHOD__ . ' execute internal request'); $processed = Request::process($this, $this->routes); if ($processed) { // 保存匹配到的路由 $this->route = Arr::get($processed, 'route'); $params = Arr::get($processed, 'params'); // 是否为外部链接 $this->external = $this->route->isExternal(); // 控制器放在子目录中的情况 if (isset($params['directory'])) { $this->directory = $params['directory']; } // 附加上命名空间 if (isset($params['namespace'])) { $this->directory = $params['namespace']; } // 命名空间处理 if (!$this->directory) { $this->directory = Route::$defaultNamespace; } // 修正命名空间 if (false === strpos($this->directory, '\\')) { $this->directory = Route::$defaultNamespace . $this->directory . '\\'; } // 保存控制器 $this->controller = Arr::get($params, 'controller'); // 保存动作 $this->action = Arr::get($params, 'action', Route::$defaultAction); // 清理保留字段 foreach ($this->persistRouteParams as $name) { unset($params[$name]); } $this->_params = $params; Base::getLog()->debug(__METHOD__ . ' execute info', ['directory' => $this->directory, 'controller' => $this->controller, 'action' => $this->action, 'params' => $this->_params]); } else { Base::getLog()->debug(__METHOD__ . ' not route matched'); } } if (!$this->route instanceof Entry) { $e = HttpException::factory(Http::NOT_FOUND, 'Unable to find a route to match the URI: :uri', [':uri' => $this->uri]); $e->request($this); throw $e; } if (!$this->client instanceof RequestClient) { throw new RequestException('Unable to execute :uri without a RequestClient', [':uri' => $this->uri]); } return $this->client->execute($this); }
/** * 覆盖原workerman流程,实现更多功能 * 当接收到完整的http请求后的处理逻辑 * * 1、如果请求的是以php为后缀的文件,则尝试加载 * 2、如果请求的url没有后缀,则尝试加载对应目录的index.php * 3、如果请求的是非php为后缀的文件,尝试读取原始数据并发送 * 4、如果请求的文件不存在,则返回404 * * @param TcpConnection $connection * @param mixed $data * @return mixed */ public function onMessage($connection, $data) { Base::getLog()->debug(__METHOD__ . ' receive http request', ['uri' => $_SERVER['REQUEST_URI'], 'ip' => $connection->getRemoteIp(), 'port' => $connection->getRemotePort(), 'data' => $data]); // 请求的文件 $urlInfo = parse_url($_SERVER['REQUEST_URI']); if (!$urlInfo) { Base::getHttp()->header('HTTP/1.1 400 Bad Request'); Base::getLog()->warning(__METHOD__ . ' receive bad request', ['uri' => $_SERVER['REQUEST_URI'], 'ip' => $connection->getRemoteIp(), 'port' => $connection->getRemotePort()]); return $connection->close($this->error400); } $path = $urlInfo['path']; $pathInfo = pathinfo($path); $extension = isset($pathInfo['extension']) ? $pathInfo['extension'] : ''; if ($extension === '') { $path = ($len = strlen($path)) && $path[$len - 1] === '/' ? $path . $this->indexFile : $path . '/' . $this->indexFile; $extension = 'php'; } $serverName = Arr::get($_SERVER, 'SERVER_NAME'); $rootDir = isset($this->serverRoot[$serverName]) ? $this->serverRoot[$serverName] : current($this->serverRoot); $file = "{$rootDir}/{$path}"; // 对应的php文件不存在,而且支持rewrite if (!is_file($file) && $this->rewrite) { $file = is_string($this->rewrite) ? $rootDir . '/' . $this->rewrite : $rootDir . '/' . $this->indexFile; $extension = 'php'; $_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI']; } // 请求的文件存在 if (is_file($file)) { Base::getLog()->debug(__METHOD__ . ' request file existed', ['file' => $file, 'extension' => $extension]); // 判断是否是站点目录里的文件 if (!($requestRealPath = realpath($file)) || !($rootDirRealPath = realpath($rootDir)) || 0 !== strpos($requestRealPath, $rootDirRealPath)) { Base::getHttp()->header('HTTP/1.1 400 Bad Request'); Base::getLog()->warning(__METHOD__ . ' receive bad request', ['uri' => $_SERVER['REQUEST_URI'], 'ip' => $connection->getRemoteIp(), 'port' => $connection->getRemotePort()]); return $connection->close('<h1>400 Bad Request</h1>'); } $file = realpath($file); // 如果请求的是php文件 // PHP文件需要include if ($extension === 'php') { Base::getLog()->debug(__METHOD__ . ' handle request', ['uri' => $_SERVER['REQUEST_URI'], 'ip' => $connection->getRemoteIp(), 'port' => $connection->getRemotePort(), 'file' => $file]); Base::getLog()->debug(__METHOD__ . ' clean components - start'); Base::cleanComponents(); Base::getLog()->debug(__METHOD__ . ' clean components - end'); $cwd = getcwd(); chdir($rootDir); ini_set('display_errors', 'off'); // 缓冲输出 ob_start(); // 载入php文件 try { // $_SERVER变量 $_SERVER['HOME'] = $_SERVER['DOCUMENT_ROOT'] = dirname($file); $_SERVER['SCRIPT_FILENAME'] = $file; Base::getLog()->debug(__METHOD__ . ' dispatch client info', ['ip' => $_SERVER['REMOTE_ADDR'], 'port' => $_SERVER['REMOTE_PORT']]); include $file; } catch (Exception $e) { Base::getLog()->error($e->getMessage(), ['code' => $e->getCode(), 'file' => $e->getFile(), 'line' => $e->getLine()]); // 如果不是exit if ($e->getMessage() != 'jump_exit') { echo $e; } } Patch::applyShutdownFunction(); $content = ob_get_clean(); ini_set('display_errors', 'on'); $result = $connection->close($content); chdir($cwd); return $result; } else { $contentType = Mime::getMimeFromExtension($extension, self::$defaultMimeType); Base::getLog()->debug(__METHOD__ . ' get static file content type', ['extension' => $extension, 'contentType' => $contentType]); Base::getHttp()->header('Content-Type: ' . $contentType); // 获取文件信息 $info = stat($file); $modifiedTime = $info ? date('D, d M Y H:i:s', Arr::get($info, 'mtime')) . ' GMT' : ''; // 如果有$_SERVER['HTTP_IF_MODIFIED_SINCE'] if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $info) { // 文件没有更改则直接304 if ($modifiedTime === $_SERVER['HTTP_IF_MODIFIED_SINCE']) { Base::getLog()->debug(__METHOD__ . ' no modified, return 304'); // 304 Base::getHttp()->header('HTTP/1.1 304 Not Modified'); // 发送给客户端 return $connection->close(''); } } if ($modifiedTime) { Base::getLog()->debug(__METHOD__ . ' set last modified time', ['time' => $modifiedTime]); Base::getHttp()->header("Last-Modified: {$modifiedTime}"); } // 发送给客户端 return $connection->close(file_get_contents($file)); } } else { Base::getLog()->warning(__METHOD__ . ' requested file not found', ['file' => $file]); // 404 Base::getHttp()->header("HTTP/1.1 404 Not Found"); return $connection->close($this->error404); } }
/** * 从http数据包中解析$_POST、$_GET、$_COOKIE等 * * @param string $recv_buffer * @param TcpConnection $connection * @return array */ public static function decode($recv_buffer, TcpConnection $connection) { // 初始化 Base::getLog()->debug(__METHOD__ . ' clean global variables'); $_POST = $_GET = $_COOKIE = $_REQUEST = $_SESSION = $_FILES = []; $GLOBALS['HTTP_RAW_POST_DATA'] = ''; $userInfo = posix_getpwuid(posix_getuid()); $_SERVER = ['USER' => Arr::get($userInfo, 'name', ''), 'HOME' => '', 'QUERY_STRING' => '', 'REQUEST_METHOD' => '', 'REQUEST_URI' => '', 'SERVER_PROTOCOL' => '', 'SERVER_SOFTWARE' => 'tourze/' . Base::VERSION, 'SERVER_NAME' => '', 'SCRIPT_FILENAME' => '', 'HTTP_HOST' => '', 'HTTP_USER_AGENT' => '', 'HTTP_ACCEPT' => '', 'HTTP_ACCEPT_LANGUAGE' => '', 'HTTP_ACCEPT_ENCODING' => '', 'HTTP_COOKIE' => '', 'HTTP_CONNECTION' => '', 'REMOTE_ADDR' => '', 'REMOTE_PORT' => '0', 'REQUEST_TIME' => time()]; $_SERVER['REQUEST_TIME_FLOAT'] = $_SERVER['REQUEST_TIME'] . substr((string) microtime(), 1, 5); Base::getLog()->debug(__METHOD__ . ' clean previous headers'); // 清空上次的数据 HttpCache::$header = ['Connection: keep-alive']; HttpCache::$instance = new HttpCache(); // 将header分割成数组 list($httpHeader, $httpBody) = explode("\r\n\r\n", $recv_buffer, 2); $headerData = explode("\r\n", $httpHeader); // 第一行为比较重要的一行 $firstLine = array_shift($headerData); list($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER['SERVER_PROTOCOL']) = explode(' ', $firstLine); $_SERVER['PHP_SELF'] = $_SERVER['SCRIPT_NAME'] = $_SERVER['DOCUMENT_URI'] = $_SERVER['REQUEST_URI']; Base::getLog()->debug(__METHOD__ . ' receive http request', ['method' => $_SERVER['REQUEST_METHOD'], 'uri' => $_SERVER['REQUEST_URI'], 'protocol' => $_SERVER['SERVER_PROTOCOL']]); $httpPostBoundary = ''; foreach ($headerData as $content) { // \r\n\r\n if (empty($content)) { continue; } list($key, $value) = explode(':', $content, 2); $key = strtolower($key); $value = trim($value); switch ($key) { // HTTP_HOST case 'host': $_SERVER['HTTP_HOST'] = $value; $tmp = explode(':', $value); $_SERVER['SERVER_NAME'] = $tmp[0]; if (isset($tmp[1])) { $_SERVER['SERVER_PORT'] = $tmp[1]; } break; // cookie // cookie case 'cookie': $_SERVER['HTTP_COOKIE'] = $value; parse_str(str_replace('; ', '&', $_SERVER['HTTP_COOKIE']), $_COOKIE); break; // user-agent // user-agent case 'user-agent': $_SERVER['HTTP_USER_AGENT'] = $value; break; // accept // accept case 'accept': $_SERVER['HTTP_ACCEPT'] = $value; break; // accept-language // accept-language case 'accept-language': $_SERVER['HTTP_ACCEPT_LANGUAGE'] = $value; break; // accept-encoding // accept-encoding case 'accept-encoding': $_SERVER['HTTP_ACCEPT_ENCODING'] = $value; break; // connection // connection case 'connection': $_SERVER['HTTP_CONNECTION'] = $value; break; case 'referer': $_SERVER['HTTP_REFERER'] = $value; break; case 'if-modified-since': $_SERVER['HTTP_IF_MODIFIED_SINCE'] = $value; break; case 'if-none-match': $_SERVER['HTTP_IF_NONE_MATCH'] = $value; break; case 'content-type': if (!preg_match('/boundary="?(\\S+)"?/', $value, $match)) { $_SERVER['CONTENT_TYPE'] = $value; } else { $_SERVER['CONTENT_TYPE'] = 'multipart/form-data'; $httpPostBoundary = '--' . $match[1]; } break; } } // 需要解析$_POST if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (isset($_SERVER['CONTENT_TYPE']) && $_SERVER['CONTENT_TYPE'] === 'multipart/form-data') { self::parseUploadFiles($httpBody, $httpPostBoundary); } else { parse_str($httpBody, $_POST); $GLOBALS['HTTP_RAW_POST_DATA'] = $httpBody; } } // QUERY_STRING $_SERVER['QUERY_STRING'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY); if ($_SERVER['QUERY_STRING']) { // $GET parse_str($_SERVER['QUERY_STRING'], $_GET); } else { $_SERVER['QUERY_STRING'] = ''; } // REQUEST $_REQUEST = array_merge($_GET, $_POST); // REMOTE_ADDR REMOTE_PORT $_SERVER['REMOTE_ADDR'] = $connection->getRemoteIp(); $_SERVER['REMOTE_PORT'] = $connection->getRemotePort(); // 这两处要怎么读取呢? $_SERVER['SERVER_ADDR'] = null; $_SERVER['SERVER_PORT'] = null; $result = ['get' => $_GET, 'post' => $_POST, 'cookie' => $_COOKIE, 'server' => $_SERVER, 'files' => $_FILES]; Base::getLog()->debug(__METHOD__ . ' get request data', $result); return $result; }
/** * {@inheritdoc} */ public function getMessages() { Base::getLog()->debug(__METHOD__ . ' get flash messages'); return array_merge($this->messages['prev'], $this->messages['now']); }
/** * 尝试以守护进程的方式运行 * * @throws Exception */ protected static function daemonize() { Base::getLog()->debug(__METHOD__ . ' calling daemonize', ['daemonize' => self::$daemonize]); if (!self::$daemonize) { return; } umask(0); $pid = pcntl_fork(); if (-1 === $pid) { throw new Exception('fork fail'); } elseif ($pid > 0) { exit(0); } if (-1 === posix_setsid()) { throw new Exception("setsid fail"); } // fork again avoid SVR4 system regain the control of terminal $pid = pcntl_fork(); if (-1 === $pid) { throw new Exception("fork fail"); } elseif (0 !== $pid) { exit(0); } }