From 9d394fa0ff21b7313ca0d5d8767352c3f90ea419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mr=C2=B7x?= Date: Tue, 31 Aug 2021 13:51:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/Error/Error.php | 371 ---------------------- http-server/Constrict/ResponseEmitter.php | 65 ++-- http-server/Message/Response.php | 209 +++++++----- http-server/Message/Stream.php | 2 +- http-server/Service/Http.php | 9 +- 5 files changed, 166 insertions(+), 490 deletions(-) delete mode 100644 core/Error/Error.php diff --git a/core/Error/Error.php b/core/Error/Error.php deleted file mode 100644 index 6bc58dbc..00000000 --- a/core/Error/Error.php +++ /dev/null @@ -1,371 +0,0 @@ -' . $message . '
PHP:' . $logTrace; - self::writeErrorLog($messageSave); - } - if ($show) { - self::showError('system', "
  • $message
  • ", $showTrace, 0); - } - if ($halt) { - exit(); - } else { - return $message; - } - } - - /** - * 代码执行过程回溯信息 - * - * @static - * @access public - */ - public static function debugBacktrace() - { - $skipFunc[] = 'Error->debugBacktrace'; - $show = $log = ''; - $debugBacktrace = debug_backtrace(); - ksort($debugBacktrace); - foreach ($debugBacktrace as $k => $error) { - if (!isset($error['file'])) { - // 利用反射API来获取方法/函数所在的文件和行数 - try { - if (isset($error['class'])) { - $reflection = new ReflectionMethod($error['class'], $error['function']); - } else { - $reflection = new ReflectionFunction($error['function']); - } - $error['file'] = $reflection->getFileName(); - $error['line'] = $reflection->getStartLine(); - } catch (Exception $e) { - continue; - } - } - $file = str_replace(SITE_PATH, '', $error['file']); - $func = isset($error['class']) ? $error['class'] : ''; - $func .= isset($error['type']) ? $error['type'] : ''; - $func .= isset($error['function']) ? $error['function'] : ''; - if (in_array($func, $skipFunc)) { - break; - } - $error['line'] = sprintf('%04d', $error['line']); - $show .= '
  • [Line: ' . $error['line'] . ']' . $file . '(' . $func . ')
  • '; - $log .= !empty($log) ? ' -> ' : ''; - $log .= $file . ':' . $error['line']; - } - return array($show, $log); - } - - /** - * 异常处理 - * - * @static - * @access public - * @param mixed $exception - */ - public static function exceptionError($exception) - { - if ($exception instanceof DbException) { - $type = 'db'; - } else { - $type = 'system'; - } - if ($type == 'db') { - $errorMsg = '(' . $exception->getCode() . ') '; - $errorMsg .= self::sqlClear($exception->getMessage(), $exception->getDbConfig()); - if ($exception->getSql()) { - $errorMsg .= '
    '; - $errorMsg .= self::sqlClear($exception->getSql(), $exception->getDbConfig()); - $errorMsg .= '
    '; - } - } else { - $errorMsg = $exception->getMessage(); - } - $trace = $exception->getTrace(); - krsort($trace); - $trace[] = array('file' => $exception->getFile(), 'line' => $exception->getLine(), 'function' => 'break'); - $phpMsg = array(); - foreach ($trace as $error) { - if (!empty($error['function'])) { - $fun = ''; - if (!empty($error['class'])) { - $fun .= $error['class'] . $error['type']; - } - $fun .= $error['function'] . '('; - if (!empty($error['args'])) { - $mark = ''; - foreach ($error['args'] as $arg) { - $fun .= $mark; - if (is_array($arg)) { - $fun .= 'Array'; - } elseif (is_bool($arg)) { - $fun .= $arg ? 'true' : 'false'; - } elseif (is_int($arg)) { - $fun .= (defined('SITE_DEBUG') && SITE_DEBUG) ? $arg : '%d'; - } elseif (is_float($arg)) { - $fun .= (defined('SITE_DEBUG') && SITE_DEBUG) ? $arg : '%f'; - } else { - $fun .= (defined('SITE_DEBUG') && SITE_DEBUG) ? '\'' . htmlspecialchars(substr(self::clear($arg), 0, 10)) . (strlen($arg) > 10 ? ' ...' : '') . '\'' : '%s'; - } - $mark = ', '; - } - } - $fun .= ')'; - $error['function'] = $fun; - } - if (!isset($error['line'])) { - continue; - } - $phpMsg[] = array('file' => str_replace(array(SITE_PATH, '\\'), array('', '/'), $error['file']), 'line' => $error['line'], 'function' => $error['function']); - } - self::showError($type, $errorMsg, $phpMsg); - exit(); - } - - /** - * 记录错误日志 - * - * @static - * @access public - * @param string $message - */ - public static function writeErrorLog($message) - { - return false; // 暂时不写入 - $message = self::clear($message); - $time = time(); - $file = LOG_PATH . '/' . date('Y.m.d') . '_errorlog.php'; - $hash = md5($message); - $userId = 0; - $ip = get_client_ip(); - $user = 'User: userId=' . intval($userId) . '; IP=' . $ip . '; RIP:' . $_SERVER['REMOTE_ADDR']; - $uri = 'Request: ' . htmlspecialchars(self::clear($_SERVER['REQUEST_URI'])); - $message = "\t{$time}\t$message\t$hash\t$user $uri\n"; - // 判断该$message是否在时间间隔$maxtime内已记录过,有,则不用再记录了 - if (is_file($file)) { - $fp = @fopen($file, 'rb'); - $lastlen = 50000; // 读取最后的 $lastlen 长度字节内容 - $maxtime = 60 * 10; // 时间间隔:10分钟 - $offset = filesize($file) - $lastlen; - if ($offset > 0) { - fseek($fp, $offset); - } - if ($data = fread($fp, $lastlen)) { - $array = explode("\n", $data); - if (is_array($array)) - foreach ($array as $key => $val) { - $row = explode("\t", $val); - if ($row[0] != '') { - continue; - } - if ($row[3] == $hash && ($row[1] > $time - $maxtime)) { - return; - } - } - } - } - error_log($message, 3, $file); - } - - /** - * 清除文本部分字符 - * - * @param string $message - */ - public static function clear($message) - { - return str_replace(array("\t", "\r", "\n"), " ", $message); - } - - /** - * sql语句字符清理 - * - * @static - * @access public - * @param string $message - * @param string $dbConfig - */ - public static function sqlClear($message, $dbConfig) - { - $message = self::clear($message); - if (!(defined('SITE_DEBUG') && SITE_DEBUG)) { - $message = str_replace($dbConfig['database'], '***', $message); - //$message = str_replace($dbConfig['prefix'], '***', $message); - $message = str_replace(C('DB_PREFIX'), '***', $message); - } - $message = htmlspecialchars($message); - return $message; - } - - /** - * 显示错误 - * - * @static - * @access public - * @param string $type 错误类型 db,system - * @param string $errorMsg - * @param string $phpMsg - */ - public static function showError($type, $errorMsg, $phpMsg = ''):string - { - global $_G; - ob_end_clean(); - $host = $_SERVER['HTTP_HOST']; - $title = $type == 'db' ? 'Database' : 'System'; - return << - - - $host - $title Error - - - - - -
    -

    $title Error

    -
    $errorMsg
    -EOT; - if (!empty($phpMsg)) { - echo '
    '; - echo '

    PHP Debug

    '; - echo ''; - if (is_array($phpMsg)) { - echo ''; - foreach ($phpMsg as $k => $msg) { - $k++; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - } - } else { - echo ''; - } - echo '
    No.FileLineCode
    ' . $k . '' . $msg['file'] . '' . $msg['line'] . '' . $msg['function'] . '
      ' . $phpMsg . '
    '; - } - echo << - - -EOT; - exit(); - } -} - -/** - * DB异常类 - * - * @author blog.snsgou.com - */ -class DbException extends Exception -{ - protected $sql; - protected $dbConfig; // 当前数据库配置信息 - - public function __construct($message, $code = 0, $sql = '', $dbConfig = array()) - { - $this->sql = $sql; - $this->dbConfig = $dbConfig; - parent::__construct($message, $code); - } - - public function getSql() - { - return $this->sql; - } - - public function getDbConfig() - { - return $this->dbConfig; - } -} -} diff --git a/http-server/Constrict/ResponseEmitter.php b/http-server/Constrict/ResponseEmitter.php index f4d5ed9b..80adcf54 100644 --- a/http-server/Constrict/ResponseEmitter.php +++ b/http-server/Constrict/ResponseEmitter.php @@ -3,9 +3,6 @@ namespace Server\Constrict; use Annotation\Inject; -use Exception; -use Kiri\Exception\NotFindClassException; -use ReflectionException; use Psr\Http\Message\ResponseInterface; use Server\RequestInterface; use Swoole\Server; @@ -18,43 +15,33 @@ class ResponseEmitter implements Emitter { - /** - * @var \Server\Constrict\DownloadEmitter - */ - #[Inject(DownloadEmitter::class)] - public DownloadEmitter $downloadEmitter; + /** + * @var RequestInterface + */ + #[Inject(RequestInterface::class)] + public RequestInterface $request; - /** - * @var \Server\RequestInterface - */ - #[Inject(RequestInterface::class)] - public RequestInterface $request; - - - /** - * @param \Swoole\Http\Response|\Swoole\Http2\Response $response - * @param ResponseInterface|\Server\Message\Response $emitter - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - public function sender(mixed $response, ResponseInterface $emitter): void - { - if (!empty($emitter->getHeaders()) && is_array($emitter->getHeaders())) { - foreach ($emitter->getHeaders() as $name => $values) { - $response->header($name, implode(';', $values)); - } - } - if (!empty($emitter->getCookies()) && is_array($emitter->getCookies())) { - foreach ($emitter->getCookies() as $name => $cookie) { - $response->cookie($name, ...$cookie); - } - } - $response->setStatusCode($emitter->getStatusCode()); - $response->header('Server', 'swoole'); - $response->header('Swoole-Version', swoole_version()); - $response->end($emitter->getBody()); - } + /** + * @param mixed $response + * @param \Server\Message\Response|ResponseInterface $emitter + */ + public function sender(mixed $response, ResponseInterface|\Server\Message\Response $emitter): void + { + if (!empty($emitter->getHeaders()) && is_array($emitter->getHeaders())) { + foreach ($emitter->getHeaders() as $name => $values) { + $response->header($name, implode(';', $values)); + } + } + if (!empty($emitter->getCookies()) && is_array($emitter->getCookies())) { + foreach ($emitter->getCookies() as $name => $cookie) { + $response->cookie($name, ...$cookie); + } + } + $response->setStatusCode($emitter->getStatusCode()); + $response->header('Server', 'swoole'); + $response->header('Swoole-Version', swoole_version()); + $response->end($emitter->getBody()); + } } diff --git a/http-server/Message/Response.php b/http-server/Message/Response.php index 91fece63..dffa4605 100644 --- a/http-server/Message/Response.php +++ b/http-server/Message/Response.php @@ -4,6 +4,8 @@ namespace Server\Message; use Exception; use JetBrains\PhpStorm\Pure; +use Kiri\Core\Help; +use Kiri\ToArray; use Psr\Http\Message\ResponseInterface; @@ -12,26 +14,26 @@ use Psr\Http\Message\ResponseInterface; */ class Response implements ResponseInterface, \Server\ResponseInterface { - use Message; + use Message; - public int $statusCode = 200; + public int $statusCode = 200; - public string $reasonPhrase = ''; + public string $reasonPhrase = ''; - const CONTENT_TYPE_JSON = 'application/json;charset=utf-8'; - const CONTENT_TYPE_HTML = 'text/html;charset=utf-8'; - const CONTENT_TYPE_STREAM = 'octet-stream'; - const CONTENT_TYPE_XML = 'application/xml;charset=utf-8'; + const CONTENT_TYPE_JSON = 'application/json;charset=utf-8'; + const CONTENT_TYPE_HTML = 'text/html;charset=utf-8'; + const CONTENT_TYPE_STREAM = 'octet-stream'; + const CONTENT_TYPE_XML = 'application/xml;charset=utf-8'; - /** - * - */ - #[Pure] public function __construct() - { - $this->stream = new Stream(''); - } + /** + * + */ + #[Pure] public function __construct() + { + $this->stream = new Stream(''); + } /** @@ -39,77 +41,134 @@ class Response implements ResponseInterface, \Server\ResponseInterface * @return $this * @throws Exception */ - public function withContentType(string $type): static - { - if (!in_array($type, [ - Response::CONTENT_TYPE_HTML, Response::CONTENT_TYPE_JSON, - Response::CONTENT_TYPE_STREAM, Response::CONTENT_TYPE_XML - ])) { - throw new Exception('Wrong content type.'); - } - return $this->withHeader('Content-Type', $type); - } + public function withContentType(string $type): static + { + if (!in_array($type, [ + Response::CONTENT_TYPE_HTML, Response::CONTENT_TYPE_JSON, + Response::CONTENT_TYPE_STREAM, Response::CONTENT_TYPE_XML + ])) { + throw new Exception('Wrong content type.'); + } + return $this->withHeader('Content-Type', $type); + } - /** - * @return int - */ - public function getStatusCode(): int - { - // TODO: Implement getStatusCode() method. - return $this->statusCode; - } + /** + * @return int + */ + public function getStatusCode(): int + { + // TODO: Implement getStatusCode() method. + return $this->statusCode; + } - /** - * @param int $code - * @param string $reasonPhrase - * @return static - */ - public function withStatus($code, $reasonPhrase = ''): static - { - $this->statusCode = $code; - $this->reasonPhrase = $reasonPhrase; - return $this; - } + /** + * @param int $code + * @param string $reasonPhrase + * @return static + */ + public function withStatus($code, $reasonPhrase = ''): static + { + $this->statusCode = $code; + $this->reasonPhrase = $reasonPhrase; + return $this; + } - /** - * @return string - */ - public function getReasonPhrase(): string - { - // TODO: Implement getReasonPhrase() method. - return $this->reasonPhrase; - } + /** + * @return string + */ + public function getReasonPhrase(): string + { + // TODO: Implement getReasonPhrase() method. + return $this->reasonPhrase; + } - /** - * @param $value - * @return ResponseInterface - */ - public function withAccessControlAllowHeaders($value): ResponseInterface - { - return $this->withHeader('Access-Control-Allow-Headers', $value); - } + /** + * @param $value + * @return ResponseInterface + */ + public function withAccessControlAllowHeaders($value): ResponseInterface + { + return $this->withHeader('Access-Control-Allow-Headers', $value); + } - /** - * @param $value - * @return ResponseInterface - */ - public function withAccessControlRequestMethod($value): ResponseInterface - { - return $this->withHeader('Access-Control-Request-Method', $value); - } + /** + * @param $value + * @return ResponseInterface + */ + public function withAccessControlRequestMethod($value): ResponseInterface + { + return $this->withHeader('Access-Control-Request-Method', $value); + } - /** - * @param $value - * @return ResponseInterface - */ - public function withAccessControlAllowOrigin($value): ResponseInterface - { - return $this->withHeader('Access-Control-Allow-Origin', $value); - } + /** + * @param $value + * @return ResponseInterface + */ + public function withAccessControlAllowOrigin($value): ResponseInterface + { + return $this->withHeader('Access-Control-Allow-Origin', $value); + } + + + /** + * @param $data + * @return ResponseInterface + * @throws Exception + */ + public function json($data): ResponseInterface + { + return $this->withBody(static::parser($data, self::CONTENT_TYPE_JSON)) + ->withContentType(self::CONTENT_TYPE_JSON); + } + + + /** + * @param $data + * @return ResponseInterface + * @throws Exception + */ + public function html($data): ResponseInterface + { + return $this->withBody(static::parser($data, self::CONTENT_TYPE_HTML)) + ->withContentType(self::CONTENT_TYPE_HTML); + } + + + /** + * @param $data + * @return ResponseInterface + * @throws Exception + */ + public function xml($data): ResponseInterface + { + return $this->withBody(static::parser($data, self::CONTENT_TYPE_XML)) + ->withContentType(self::CONTENT_TYPE_XML); + } + + + /** + * @param $responseData + * @param string $contentType + * @return Stream + * @throws Exception + */ + public static function parser($responseData, $contentType = self::CONTENT_TYPE_JSON): Stream + { + if (is_object($responseData)) { + $responseData = $responseData instanceof ToArray ? $responseData->toArray() : get_object_vars($responseData); + } + if ($contentType == self::CONTENT_TYPE_JSON) { + return new Stream(json_encode($responseData)); + } + if ($contentType == self::CONTENT_TYPE_XML) { + return new Stream(Help::toXml($responseData)); + } + return new Stream((string)($responseData)); + } } diff --git a/http-server/Message/Stream.php b/http-server/Message/Stream.php index 89db7fe2..d0d05b33 100644 --- a/http-server/Message/Stream.php +++ b/http-server/Message/Stream.php @@ -143,7 +143,7 @@ class Stream implements StreamInterface * @param string $string * @return int */ - public function append($string): int + public function append(string $string): int { $this->body .= $string; $this->size = strlen($this->body); diff --git a/http-server/Service/Http.php b/http-server/Service/Http.php index ca93bc0d..942a58ab 100644 --- a/http-server/Service/Http.php +++ b/http-server/Service/Http.php @@ -58,10 +58,11 @@ class Http extends \Server\Abstracts\Http implements OnClose, OnConnect } - /** - * @param $responseData - * @return \Server\ResponseInterface - */ + /** + * @param $responseData + * @return ResponseInterface + * @throws Exception + */ private function transferToResponse($responseData): ResponseInterface { $interface = $this->response->withStatus(200);