Exemple #1
0
 /**
  * 实现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'));
     }
 }
Exemple #2
0
 /**
  * @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();
 }
Exemple #4
0
 /**
  * 每个请求层,最终被调用的方法
  *
  * @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');
 }
Exemple #5
0
 /**
  * @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]);
 }
Exemple #6
0
 /**
  * {@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 . ')';
     }
 }
Exemple #8
0
 /**
  * 每个请求层,最终被调用的方法
  *
  * @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');
 }
Exemple #9
0
 /**
  * 处理请求统计
  *
  * @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']));
 }
Exemple #10
0
 /**
  * {@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();
 }
Exemple #11
0
 /**
  * 处理请求
  *
  *     $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;
 }
Exemple #13
0
 /**
  * 上报统计数据
  *
  * @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);
 }
Exemple #14
0
Fichier : Db.php Projet : tourze/db
 /**
  * 单例模式,获取一个指定的实例
  *
  *     // 加载默认实例
  *     $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];
 }
Exemple #15
0
 /**
  * 跳转的助手方法
  *
  * @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);
 }
Exemple #16
0
 /**
  * 删除当前记录
  *
  * @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();
 }
Exemple #17
0
 /**
  * 格式化日志记录
  *
  * @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;
 }
Exemple #18
0
 /**
  * {@inheritdoc}
  */
 public function destroy()
 {
     Base::getLog()->debug(__METHOD__ . ' destroy session');
     return session_destroy();
 }
Exemple #19
0
 /**
  * {@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;
 }
Exemple #20
0
 /**
  * 传入参数,生成当前路由的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;
 }
Exemple #21
0
 /**
  * 解析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;
     }
 }
Exemple #22
0
 /**
  * 记录异常信息
  *
  * @param Exception $e
  */
 public static function log(Exception $e)
 {
     Base::getLog()->error($e->getMessage(), ['code' => $e->getCode(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
 }
Exemple #23
0
 /**
  * {@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);
 }
Exemple #24
0
 /**
  * 获取指定的路由信息
  *
  *     $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];
 }
Exemple #25
0
 /**
  * {@inheritdoc}
  */
 public function remove($name)
 {
     Base::getLog()->debug(__METHOD__ . ' remove cache', ['name' => $name]);
     unset($this->_cache[$name]);
     unset($this->_cacheHit[$name]);
     return true;
 }
Exemple #26
0
 /**
  * 执行请求
  *
  * @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);
 }
Exemple #27
0
 /**
  * 覆盖原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);
     }
 }
Exemple #28
0
 /**
  * 从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;
 }
Exemple #29
0
 /**
  * {@inheritdoc}
  */
 public function getMessages()
 {
     Base::getLog()->debug(__METHOD__ . ' get flash messages');
     return array_merge($this->messages['prev'], $this->messages['now']);
 }
Exemple #30
0
 /**
  * 尝试以守护进程的方式运行
  *
  * @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);
     }
 }