diff --git a/Annotation/Inject.php b/Annotation/Inject.php index 4bcc4d8c..047dbe86 100644 --- a/Annotation/Inject.php +++ b/Annotation/Inject.php @@ -19,11 +19,12 @@ use Snowflake\Snowflake; { - /** - * Inject constructor. - * @param string $value - * @param array $args - */ + /** + * Inject constructor. + * @param string $value + * @param bool $withContext + * @param array $args + */ public function __construct(private string $value, public bool $withContext = false, private array $args = []) { } @@ -78,7 +79,7 @@ use Snowflake\Snowflake; return $method; } if (is_object($class)) $class = $class::class; - $method = Snowflake::getDi()->getClassProperty($class, $method); + $method = Snowflake::getDi()->getClassReflectionProperty($class, $method); if (!$method || $method->isStatic()) { return false; } diff --git a/Annotation/Loader.php b/Annotation/Loader.php index 9e9aed3c..9c44bede 100644 --- a/Annotation/Loader.php +++ b/Annotation/Loader.php @@ -4,15 +4,10 @@ namespace Annotation; -use Annotation\Model\Get; -use Annotation\Model\Relation; -use Annotation\Model\Set; -use Attribute; use DirectoryIterator; use Exception; use ReflectionClass; use ReflectionException; -use ReflectionMethod; use Snowflake\Abstracts\BaseObject; use Snowflake\Exception\NotFindClassException; use Snowflake\Snowflake; @@ -27,204 +22,206 @@ class Loader extends BaseObject { - private static array $_classes = []; + private static array $_classes = []; - private static array $_directory = []; + private static array $_directory = []; - private static array $_property = []; + private static array $_property = []; - private static array $_methods = []; + private static array $_methods = []; - /** - * @param $path - * @param $namespace - * @throws Exception - */ - public function loader($path, $namespace) - { - $this->_scanDir(new DirectoryIterator($path), $namespace); - } + /** + * @param $path + * @param $namespace + * @throws Exception + */ + public function loader($path, $namespace) + { + $this->_scanDir(new DirectoryIterator($path), $namespace); + } - /** - * @param string $class - * @param string $property - * @return mixed - */ - public function getProperty(string $class, string $property = ''): mixed - { - if (!isset(static::$_property[$class])) { - return null; - } - if (!empty($property)) { - return static::$_property[$class][$property] ?? []; - } - return static::$_property[$class]; - } + /** + * @param string $class + * @param string $property + * @return mixed + */ + public function getProperty(string $class, string $property = ''): mixed + { + return Snowflake::getDi()->getClassReflectionProperty($class, $property); + + if (!isset(static::$_property[$class])) { + return null; + } + if (!empty($property)) { + return static::$_property[$class][$property] ?? []; + } + return static::$_property[$class]; + } - /** - * @param string $class - * @param mixed $handler - * @return Loader - */ - public function injectProperty(string $class, object $handler): static - { - $properties = $this->getProperty($class); - if (empty($properties)) { - return $this; - } - foreach ($properties as $property => $attributes) { - foreach ($attributes as $attribute) { - $attribute->execute($handler, $property); - } - } - return $this; - } + /** + * @param string $class + * @param object $handler + * @return $this + * @throws NotFindClassException + * @throws ReflectionException + * @throws Exception + */ + public function injectProperty(string $class, object $handler): static + { + $di = Snowflake::getDi(); + + $reflect = $di->getReflect($class); + + $di->propertyInject($reflect, $handler); + + return $this; + } - /** - * @param string $class - * @param string $method - * @return mixed - */ - public function getMethod(string $class, string $method = ''): array - { - if (!isset(static::$_methods[$class])) { - return []; - } - $properties = static::$_methods[$class]; - if (!empty($method) && isset($properties[$method])) { - return $properties[$method]; - } - return $properties; - } + /** + * @param string $class + * @param string $method + * @return mixed + */ + public function getMethod(string $class, string $method = ''): array + { + if (!isset(static::$_methods[$class])) { + return []; + } + $properties = static::$_methods[$class]; + if (!empty($method) && isset($properties[$method])) { + return $properties[$method]; + } + return $properties; + } - /** - * @param DirectoryIterator $paths - * @param $namespace - * @throws Exception - */ - public function _scanDir(DirectoryIterator $paths, $namespace) - { - foreach ($paths as $path) { - if ($path->isDot() || str_starts_with($path->getFilename(), '.')) { - continue; - } - if ($path->isDir()) { - $iterator = new DirectoryIterator($path->getRealPath()); - $directory = rtrim($path->getRealPath(), '/'); - if (!isset(static::$_directory[$directory])) { - static::$_directory[$directory] = []; - } - $this->_scanDir($iterator, $namespace); - } else { - $this->readFile($path, $namespace); - } - } - } + /** + * @param DirectoryIterator $paths + * @param $namespace + * @throws Exception + */ + public function _scanDir(DirectoryIterator $paths, $namespace) + { + foreach ($paths as $path) { + if ($path->isDot() || str_starts_with($path->getFilename(), '.')) { + continue; + } + if ($path->isDir()) { + $iterator = new DirectoryIterator($path->getRealPath()); + $directory = rtrim($path->getRealPath(), '/'); + if (!isset(static::$_directory[$directory])) { + static::$_directory[$directory] = []; + } + $this->_scanDir($iterator, $namespace); + } else { + $this->readFile($path, $namespace); + } + } + } - /** - * @param DirectoryIterator $path - * @param $namespace - * @throws Exception - */ - private function readFile(DirectoryIterator $path, $namespace) - { - try { - if ($path->getExtension() !== 'php') { - return; - } - $replace = $this->getReflect($path, $namespace); - if (empty($replace) || count($replace->getAttributes(Target::class)) < 1) { - return; - } - $this->appendFileToDirectory($path->getRealPath(), $replace->getName()); + /** + * @param DirectoryIterator $path + * @param $namespace + * @throws Exception + */ + private function readFile(DirectoryIterator $path, $namespace) + { + try { + if ($path->getExtension() !== 'php') { + return; + } + $replace = $this->getReflect($path, $namespace); + if (empty($replace) || count($replace->getAttributes(Target::class)) < 1) { + return; + } + $this->appendFileToDirectory($path->getRealPath(), $replace->getName()); - static::$_classes[] = $replace->getName(); - } catch (Throwable $throwable) { - $this->addError($throwable, 'throwable'); - } - } + static::$_classes[] = $replace->getName(); + } catch (Throwable $throwable) { + $this->addError($throwable, 'throwable'); + } + } - /** - * @param DirectoryIterator $path - * @param string $namespace - * @return ReflectionClass|null - * @throws ReflectionException - * @throws NotFindClassException - */ - private function getReflect(DirectoryIterator $path, string $namespace): ?ReflectionClass - { - return Snowflake::getDi()->getReflect($this->explodeFileName($path, $namespace)); - } + /** + * @param DirectoryIterator $path + * @param string $namespace + * @return ReflectionClass|null + * @throws ReflectionException + * @throws NotFindClassException + */ + private function getReflect(DirectoryIterator $path, string $namespace): ?ReflectionClass + { + return Snowflake::getDi()->getReflect($this->explodeFileName($path, $namespace)); + } - /** - * @param string $path - * @param string|array $outPath - * @throws Exception - */ - public function loadByDirectory(string $path) - { - try { - $path = '/' . trim($path, '/'); + /** + * @param string $path + * @param string|array $outPath + * @throws Exception + */ + public function loadByDirectory(string $path) + { + try { + $path = '/' . trim($path, '/'); - $paths = []; - foreach (static::$_directory as $key => $_path) { - $key = '/' . trim($key, '/'); - if (!str_starts_with($key, $path)) { - continue; - } - foreach ($_path as $item) { - $paths[] = $item; - } - } - return $paths; - } catch (Throwable $exception) { - $this->addError($exception, 'throwable'); - return []; - } - } + $paths = []; + foreach (static::$_directory as $key => $_path) { + $key = '/' . trim($key, '/'); + if (!str_starts_with($key, $path)) { + continue; + } + foreach ($_path as $item) { + $paths[] = $item; + } + } + return $paths; + } catch (Throwable $exception) { + $this->addError($exception, 'throwable'); + return []; + } + } - /** - * @param DirectoryIterator $path - * @param string $namespace - * @return string - */ - private function explodeFileName(DirectoryIterator $path, string $namespace): string - { - $replace = str_replace(APP_PATH . 'app', '', $path->getRealPath()); + /** + * @param DirectoryIterator $path + * @param string $namespace + * @return string + */ + private function explodeFileName(DirectoryIterator $path, string $namespace): string + { + $replace = str_replace(APP_PATH . 'app', '', $path->getRealPath()); - $replace = str_replace('.php', '', $replace); - $replace = str_replace(DIRECTORY_SEPARATOR, '\\', $replace); - $explode = explode('\\', $replace); - array_shift($explode); + $replace = str_replace('.php', '', $replace); + $replace = str_replace(DIRECTORY_SEPARATOR, '\\', $replace); + $explode = explode('\\', $replace); + array_shift($explode); - return $namespace . '\\' . implode('\\', $explode); - } + return $namespace . '\\' . implode('\\', $explode); + } - /** - * @param string $filePath - * @param string $className - */ - public function appendFileToDirectory(string $filePath, string $className) - { - $array = explode('/', $filePath); - unset($array[count($array) - 1]); + /** + * @param string $filePath + * @param string $className + */ + public function appendFileToDirectory(string $filePath, string $className) + { + $array = explode('/', $filePath); + unset($array[count($array) - 1]); - $array = '/' . trim(implode('/', $array), '/'); + $array = '/' . trim(implode('/', $array), '/'); - static::$_directory[$array][] = $className; - } + static::$_directory[$array][] = $className; + } } diff --git a/Annotation/Route/After.php b/Annotation/Route/After.php deleted file mode 100644 index b2f8cdc7..00000000 --- a/Annotation/Route/After.php +++ /dev/null @@ -1,48 +0,0 @@ -after)) { - $this->after = [$this->after]; - } - foreach ($this->after as $key => $value) { - $sn = Snowflake::createObject($value); - if (!($sn instanceof \HttpServer\IInterface\After)) { - continue; - } - $this->after[$key] = [$sn, 'onHandler']; - } - } - - - /** - * @param mixed $class - * @param mixed|null $method - * @return After - */ - public function execute(mixed $class, mixed $method = null): static - { - return $this; - } - - -} diff --git a/HttpServer/Http/Request.php b/HttpServer/Http/Request.php index 09c30a3b..284756d2 100644 --- a/HttpServer/Http/Request.php +++ b/HttpServer/Http/Request.php @@ -3,17 +3,12 @@ declare(strict_types=1); namespace HttpServer\Http; -use Annotation\Route\Socket; use Exception; use HttpServer\Abstracts\HttpService; -use HttpServer\Http\Response as HResponse; use HttpServer\IInterface\AuthIdentity; use JetBrains\PhpStorm\Pure; -use Snowflake\Abstracts\Config; -use Snowflake\Core\ArrayAccess; use Snowflake\Core\Help; use Snowflake\Core\Json; -use Snowflake\Exception\ConfigException; use Snowflake\Snowflake; use function router; @@ -38,442 +33,456 @@ defined('REQUEST_FAIL') or define('REQUEST_FAIL', 500); class Request extends HttpService { - public int $fd = 0; - - public ?HttpParams $params; - - public ?HttpHeaders $headers; - - public bool $isCli = FALSE; - - public float $startTime; - public ?array $clientInfo; - - public string $uri = ''; - - public int $statusCode = 200; - - /** @var string[] */ - private array $explode = []; - - const PLATFORM_MAC_OX = 'mac'; - const PLATFORM_IPHONE = 'iphone'; - const PLATFORM_ANDROID = 'android'; - const PLATFORM_WINDOWS = 'windows'; - - - const HTTP_POST = 'post'; - const HTTP_GET = 'get'; - const HTTP_CMD = 'rpc'; - const HTTP_LISTEN = 'listen'; - const HTTP_SOCKET = 'sw::socket'; - - - /** - * @var AuthIdentity|null - */ - private ?AuthIdentity $_grant = null; - - - /** - * @param $fd - */ - public function setFd($fd) - { - $this->fd = $fd; - } - - /** - * @return array|null - * @throws Exception - */ - public function getConnectInfo(): array|null - { - if (empty($this->fd)) { - return null; - } - $server = Snowflake::app()->getSwoole(); - - return $server->getClientInfo($this->fd); - } - - - /** - * @return int - */ - public function getClientId(): int - { - return $this->fd; - } - - - /** - * @return bool - */ - public function isFavicon(): bool - { - return $this->getUri() === 'favicon.ico'; - } - - /** - * @return AuthIdentity|null - */ - public function getIdentity(): ?AuthIdentity - { - return $this->_grant; - } - - /** - * @return bool - */ - public function isHead(): bool - { - $result = $this->headers->getHeader('request_method') == 'head'; - if ($result) { - $this->setStatus(101); - } else { - $this->setStatus(200); - } - return $result; - } - - /** - * @param $status - * @return mixed - */ - public function setStatus($status): mixed - { - return $this->statusCode = $status; - } - - /** - * @return int - */ - public function getStatus(): int - { - return $this->statusCode; - } - - /** - * @return bool - */ - public function getIsPackage(): bool - { - return $this->headers->getHeader('request_method') == 'package'; - } - - /** - * @return bool - */ - public function getIsReceive(): bool - { - return $this->headers->getHeader('request_method') == 'receive'; - } - - - /** - * @param $value - */ - public function setGrantAuthorization($value) - { - $this->_grant = $value; - } - - - /** - * @return bool - */ - public function hasGrant(): bool - { - return $this->_grant !== null; - } - - - /** - * @return string - */ - public function parseUri(): string - { - $array = []; - $explode = explode('/', $this->headers->getHeader('request_uri')); - foreach ($explode as $item) { - if (empty($item)) { - continue; - } - $array[] = $item; - } - return $this->uri = implode('/', ($this->explode = $array)); - } - - /** - * @return string[] - */ - public function getExplode(): array - { - return $this->explode; - } - - /** - * @return string - */ - #[Pure] public function getCurrent(): string - { - return current($this->explode); - } - - /** - * @return string - */ - public function getUri(): string - { - if (!$this->headers) { - return 'command exec.'; - } - if (!empty($this->uri)) { - return $this->uri; - } - $uri = $this->headers->getHeader('request_uri'); - $uri = ltrim($uri, '/'); - if (empty($uri)) return '/'; - return $uri; - } - - - /** - * @return mixed - * @throws Exception - */ - public function adapter(): void - { - if (!$this->isHead()) { - router()->dispatch(); - } - } - - - /** - * @return string|null - */ - public function getPlatform(): ?string - { - $user = $this->headers->getHeader('user-agent'); - $match = preg_match('/\(.*\)?/', $user, $output); - if (!$match || count($output) < 1) { - return null; - } - $output = strtolower(array_shift($output)); - if (strpos('mac', $output)) { - return 'mac'; - } else if (strpos('iphone', $output)) { - return 'iphone'; - } else if (strpos('android', $output)) { - return 'android'; - } else if (strpos('windows', $output)) { - return 'windows'; - } - return null; - } - - /** - * @return bool - */ - public function isIos(): bool - { - return $this->getPlatform() == static::PLATFORM_IPHONE; - } - - /** - * @return bool - */ - public function isAndroid(): bool - { - return $this->getPlatform() == static::PLATFORM_ANDROID; - } - - /** - * @return bool - */ - public function isMacOs(): bool - { - return $this->getPlatform() == static::PLATFORM_MAC_OX; - } - - /** - * @return bool - */ - public function isWindows(): bool - { - return $this->getPlatform() == static::PLATFORM_WINDOWS; - } - - /** - * @return bool - */ - public function getIsPost(): bool - { - return $this->getMethod() == 'post'; - } - - /** - * @return bool - * @throws Exception - */ - public function getIsHttp(): bool - { - return true; - } - - /** - * @return bool - */ - public function getIsOption(): bool - { - return $this->getMethod() == 'options'; - } - - /** - * @return bool - */ - public function getIsGet(): bool - { - return $this->getMethod() == 'get'; - } - - /** - * @return bool - */ - public function getIsDelete(): bool - { - return $this->getMethod() == 'delete'; - } - - /** - * @return string - * - * 获取请求类型 - */ - public function getMethod(): string - { - $method = $this->headers->get('request_method'); - if (empty($method)) { - return 'get'; - } - return strtolower($method); - } - - /** - * @return bool - */ - public function getIsCli(): bool - { - return $this->isCli === TRUE; - } - - - /** - * @param $name - * @param $value - * - * @throws Exception - */ - public function __set($name, $value) - { - $method = 'set' . ucfirst($name); - if (method_exists($this, $method)) { - $this->$method($value); - } else { - parent::__set($name, $value); // TODO: Change the autogenerated stub - } - } - - /** - * @return mixed|null - */ - #[Pure] public function getIp(): string|null - { - $headers = $this->headers->getHeaders(); - if (!empty($headers['remoteip'])) return $headers['remoteip']; - if (!empty($headers['x-forwarded-for'])) return $headers['x-forwarded-for']; - if (!empty($headers['request-ip'])) return $headers['request-ip']; - if (!empty($headers['remote_addr'])) return $headers['remote_addr']; - return NULL; - } - - /** - * @return string - */ - #[Pure] public function getRuntime(): string - { - return sprintf('%.5f', microtime(TRUE) - $this->startTime); - } - - /** - * @return string - */ - public function getDebug(): string - { - $mainstay = sprintf("%.6f", microtime(true)); // 带毫秒的时间戳 - - $timestamp = floatval($mainstay); // 时间戳 - $milliseconds = round(($mainstay - $timestamp) * 1000); // 毫秒 - - $datetime = date("Y-m-d H:i:s", (int)$timestamp) . '.' . $milliseconds; - - $tmp = [ - '[Debug ' . $datetime . '] ', - $this->getIp(), - $this->getUri(), - '`' . $this->headers->getHeader('user-agent') . '`', - $this->getRuntime() - ]; - return implode(' ', $tmp); - } - - - /** - * @param $router - * @return bool - */ - public function is($router): bool - { - return $this->getUri() == $router; - } - - /** - * @return bool - */ - public function isNotFound(): bool - { - return Json::to(404, 'Page ' . $this->getUri() . ' not found.'); - } - - - /** - * @param \Swoole\Http\Request $request - * @return mixed - */ - public static function create(\Swoole\Http\Request $request): Request - { - /** @var Request $sRequest */ - $sRequest = Context::setContext('request', new Request()); - $sRequest->fd = $request->fd; - $sRequest->startTime = microtime(true); - - $sRequest->params = new HttpParams(Help::toArray($request->rawContent()), $request->get, $request->files); - if (!empty($request->post)) { - $sRequest->params->setPosts($request->post ?? []); - } - Context::setContext(HttpParams::class, $sRequest->params); - - $sRequest->headers = new HttpHeaders(array_merge($request->server, $request->header)); - Context::setContext(HttpHeaders::class, $sRequest->headers); - - $sRequest->uri = $sRequest->headers->get('request_uri'); - - $sRequest->parseUri(); - - return $sRequest; - } + public int $fd = 0; + + public ?HttpParams $params; + + public ?HttpHeaders $headers; + + public bool $isCli = FALSE; + + public float $startTime; + public ?array $clientInfo; + + public string $uri = ''; + + public int $statusCode = 200; + + /** @var string[] */ + private array $explode = []; + + const PLATFORM_MAC_OX = 'mac'; + const PLATFORM_IPHONE = 'iphone'; + const PLATFORM_ANDROID = 'android'; + const PLATFORM_WINDOWS = 'windows'; + + + const HTTP_POST = 'post'; + const HTTP_GET = 'get'; + const HTTP_CMD = 'rpc'; + const HTTP_LISTEN = 'listen'; + const HTTP_SOCKET = 'sw::socket'; + + + /** + * @var AuthIdentity|null + */ + private ?AuthIdentity $_grant = null; + + + /** + * @param $fd + */ + public function setFd($fd) + { + $this->fd = $fd; + } + + /** + * @return array|null + * @throws Exception + */ + public function getConnectInfo(): array|null + { + if (empty($this->fd)) { + return null; + } + $server = Snowflake::app()->getSwoole(); + + return $server->getClientInfo($this->fd); + } + + + /** + * @return int + */ + public function getClientId(): int + { + return $this->fd; + } + + + /** + * @return bool + */ + public function isFavicon(): bool + { + return $this->getUri() === 'favicon.ico'; + } + + /** + * @return AuthIdentity|null + */ + public function getIdentity(): ?AuthIdentity + { + return $this->_grant; + } + + /** + * @return bool + */ + public function isHead(): bool + { + $result = $this->headers->getHeader('request_method') == 'head'; + if ($result) { + $this->setStatus(101); + } else { + $this->setStatus(200); + } + return $result; + } + + /** + * @param $status + * @return mixed + */ + public function setStatus($status): mixed + { + return $this->statusCode = $status; + } + + /** + * @return int + */ + public function getStatus(): int + { + return $this->statusCode; + } + + /** + * @return bool + */ + public function getIsPackage(): bool + { + return $this->headers->getHeader('request_method') == 'package'; + } + + /** + * @return bool + */ + public function getIsReceive(): bool + { + return $this->headers->getHeader('request_method') == 'receive'; + } + + + /** + * @param $value + */ + public function setGrantAuthorization($value) + { + $this->_grant = $value; + } + + + /** + * @return bool + */ + public function hasGrant(): bool + { + return $this->_grant !== null; + } + + + /** + * @return string + */ + public function parseUri(): string + { + $array = []; + $explode = explode('/', $this->headers->getHeader('request_uri')); + foreach ($explode as $item) { + if (empty($item)) { + continue; + } + $array[] = $item; + } + return $this->uri = implode('/', ($this->explode = $array)); + } + + /** + * @return string[] + */ + public function getExplode(): array + { + return $this->explode; + } + + /** + * @return string + */ + #[Pure] public function getCurrent(): string + { + return current($this->explode); + } + + /** + * @return string + */ + public function getUri(): string + { + if (!$this->headers) { + return 'command exec.'; + } + if (!empty($this->uri)) { + return $this->uri; + } + $uri = $this->headers->getHeader('request_uri'); + $uri = ltrim($uri, '/'); + if (empty($uri)) return '/'; + return $uri; + } + + + /** + * @return mixed + * @throws Exception + */ + public function adapter(): void + { + if (!$this->isHead()) { + router()->dispatch(); + } + } + + + /** + * @return string|null + */ + public function getPlatform(): ?string + { + $user = $this->headers->getHeader('user-agent'); + $match = preg_match('/\(.*\)?/', $user, $output); + if (!$match || count($output) < 1) { + return null; + } + $output = strtolower(array_shift($output)); + if (strpos('mac', $output)) { + return 'mac'; + } else if (strpos('iphone', $output)) { + return 'iphone'; + } else if (strpos('android', $output)) { + return 'android'; + } else if (strpos('windows', $output)) { + return 'windows'; + } + return null; + } + + /** + * @return bool + */ + public function isIos(): bool + { + return $this->getPlatform() == static::PLATFORM_IPHONE; + } + + /** + * @return bool + */ + public function isAndroid(): bool + { + return $this->getPlatform() == static::PLATFORM_ANDROID; + } + + /** + * @return bool + */ + public function isMacOs(): bool + { + return $this->getPlatform() == static::PLATFORM_MAC_OX; + } + + /** + * @return bool + */ + public function isWindows(): bool + { + return $this->getPlatform() == static::PLATFORM_WINDOWS; + } + + /** + * @return bool + */ + public function getIsPost(): bool + { + return $this->getMethod() == 'post'; + } + + /** + * @return bool + * @throws Exception + */ + public function getIsHttp(): bool + { + return true; + } + + /** + * @return bool + */ + public function getIsOption(): bool + { + return $this->getMethod() == 'options'; + } + + /** + * @return bool + */ + public function getIsGet(): bool + { + return $this->getMethod() == 'get'; + } + + /** + * @return bool + */ + public function getIsDelete(): bool + { + return $this->getMethod() == 'delete'; + } + + /** + * @return string + * + * 获取请求类型 + */ + public function getMethod(): string + { + $method = $this->headers->get('request_method'); + if (empty($method)) { + return 'get'; + } + return strtolower($method); + } + + /** + * @return bool + */ + public function getIsCli(): bool + { + return $this->isCli === TRUE; + } + + + /** + * @param $name + * @param $value + * + * @throws Exception + */ + public function __set($name, $value) + { + $method = 'set' . ucfirst($name); + if (method_exists($this, $method)) { + $this->$method($value); + } else { + parent::__set($name, $value); // TODO: Change the autogenerated stub + } + } + + /** + * @return mixed|null + */ + #[Pure] public function getIp(): string|null + { + $headers = $this->headers->getHeaders(); + if (!empty($headers['remoteip'])) return $headers['remoteip']; + if (!empty($headers['x-forwarded-for'])) return $headers['x-forwarded-for']; + if (!empty($headers['request-ip'])) return $headers['request-ip']; + if (!empty($headers['remote_addr'])) return $headers['remote_addr']; + return NULL; + } + + /** + * @return string + */ + #[Pure] public function getRuntime(): string + { + return sprintf('%.5f', microtime(TRUE) - $this->startTime); + } + + /** + * @return string + */ + public function getDebug(): string + { + $mainstay = sprintf("%.6f", microtime(true)); // 带毫秒的时间戳 + + $timestamp = floatval($mainstay); // 时间戳 + $milliseconds = round(($mainstay - $timestamp) * 1000); // 毫秒 + + $datetime = date("Y-m-d H:i:s", (int)$timestamp) . '.' . $milliseconds; + + $tmp = [ + '[Debug ' . $datetime . '] ', + $this->getIp(), + $this->getUri(), + '`' . $this->headers->getHeader('user-agent') . '`', + $this->getRuntime() + ]; + return implode(' ', $tmp); + } + + + /** + * @param $router + * @return bool + */ + public function is($router): bool + { + return $this->getUri() == $router; + } + + /** + * @return bool + */ + public function isNotFound(): bool + { + return Json::to(404, 'Page ' . $this->getUri() . ' not found.'); + } + + + /** + * @param \Swoole\Http\Request $request + * @return mixed + */ + public static function create(\Swoole\Http\Request $request): Request + { + /** @var Request $sRequest */ + $sRequest = Context::setContext('request', new Request()); + + $sRequest->fd = $request->fd; + $sRequest->startTime = microtime(true); + + $sRequest->params = new HttpParams(Help::toArray($request->rawContent()), $request->get, $request->files); + if (!empty($request->post)) { + $sRequest->params->setPosts($request->post ?? []); + } + Context::setContext(HttpParams::class, $sRequest->params); + + $sRequest->headers = new HttpHeaders(array_merge($request->server, $request->header)); + Context::setContext(HttpHeaders::class, $sRequest->headers); + + $sRequest->uri = $sRequest->headers->get('request_uri'); + + $sRequest->parseUri(); + + return $sRequest; + } + + + /** + * @param string $key + * @param mixed|null $defaultValue + * @return mixed + */ + public function post(string $key, mixed $defaultValue = null): mixed + { + /** @var HttpParams $params */ + $params = Context::getContext(HttpParams::class); + return $params->post($key, $defaultValue); + } } diff --git a/HttpServer/Route/MiddlewareManager.php b/HttpServer/Route/MiddlewareManager.php index 0336dbac..80c1b19a 100644 --- a/HttpServer/Route/MiddlewareManager.php +++ b/HttpServer/Route/MiddlewareManager.php @@ -4,6 +4,7 @@ namespace HttpServer\Route; +use Closure; use HttpServer\IInterface\Middleware; use Snowflake\Abstracts\BaseObject; @@ -15,72 +16,91 @@ use Snowflake\Abstracts\BaseObject; class MiddlewareManager extends BaseObject { - private static array $_middlewares = []; + private static array $_middlewares = []; - /** - * @param $class - * @param $method - * @param array|string $middlewares - */ - public function addMiddlewares($class, $method, array|string $middlewares) - { - if (is_object($class)) { - $class = $class::class; - } - if (!isset(static::$_middlewares[$class . '::' . $method])) { - static::$_middlewares[$class . '::' . $method] = []; - } + /** + * @param $class + * @param $method + * @param array|string $middlewares + */ + public function addMiddlewares($class, $method, array|string $middlewares) + { + if (is_object($class)) { + $class = $class::class; + } + if (!isset(static::$_middlewares[$class . '::' . $method])) { + static::$_middlewares[$class . '::' . $method] = []; + } - if (is_string($middlewares) && !in_array($middlewares, static::$_middlewares[$class . '::' . $method])) { - static::$_middlewares[$class . '::' . $method][] = $middlewares; - return; - } - foreach ($middlewares as $middleware) { - if (in_array($middlewares, static::$_middlewares[$class . '::' . $method])) { - continue; - } - static::$_middlewares[$class . '::' . $method][] = $middleware; - } - } + if (is_string($middlewares) && !in_array($middlewares, static::$_middlewares[$class . '::' . $method])) { + static::$_middlewares[$class . '::' . $method][] = $middlewares; + return; + } + foreach ($middlewares as $middleware) { + if (in_array($middlewares, static::$_middlewares[$class . '::' . $method])) { + continue; + } + static::$_middlewares[$class . '::' . $method][] = $middleware; + } + } - /** - * @param $class - * @param $method - * @return bool - */ - public function hasMiddleware($class, $method) - { - if (is_object($class)) { - $class = $class::class; - } - return isset(static::$_middlewares[$class . '::' . $method]); - } + /** + * @param $class + * @param $method + * @return bool + */ + public function hasMiddleware($class, $method): bool + { + if (is_object($class)) { + $class = $class::class; + } + return isset(static::$_middlewares[$class . '::' . $method]); + } - /** - * @param $class - * @param $method - * @param $caller - */ - public function callerMiddlewares($class, $method, $caller) - { - if (is_object($class)) { - $class = $class::class; - } - $middlewares = static::$_middlewares[$class . '::' . $method] ?? []; - if (empty($middlewares)) { - return $caller; - } - return array_reduce(array_reverse($middlewares), function ($stack, $pipe) { - return function ($passable) use ($stack, $pipe) { - if ($pipe instanceof Middleware) { - return $pipe->onHandler($passable, $stack); - } - return call_user_func($pipe, $passable, $stack); - }; - }, $caller); - } + /** + * @param $class + * @param $method + * @param $caller + * @return mixed + */ + public function callerMiddlewares($class, $method, $caller): mixed + { + if (is_object($class)) { + $class = $class::class; + } + $middlewares = static::$_middlewares[$class . '::' . $method] ?? []; + if (empty($middlewares)) { + return $caller; + } + return array_reduce(array_reverse($middlewares), function ($stack, $pipe) { + return function ($passable) use ($stack, $pipe) { + if ($pipe instanceof Middleware) { + return $pipe->onHandler($passable, $stack); + } + return call_user_func($pipe, $passable, $stack); + }; + }, $caller); + } + + + /** + * @param $middlewares + * @param Closure $caller + * @return Closure + */ + public function closureMiddlewares($middlewares, Closure $caller): Closure + { + return array_reduce(array_reverse($middlewares), function ($stack, $pipe) { + return function ($passable) use ($stack, $pipe) { + if ($pipe instanceof Middleware) { + return $pipe->onHandler($passable, $stack); + } + return call_user_func($pipe, $passable, $stack); + }; + }, $caller); + } } diff --git a/HttpServer/Route/Node.php b/HttpServer/Route/Node.php index 89a3fc99..5bea1bfe 100644 --- a/HttpServer/Route/Node.php +++ b/HttpServer/Route/Node.php @@ -94,8 +94,26 @@ class Node extends HttpService } else { $this->handler = $handler; } - if (!empty($this->handler) && is_array($this->handler)) { - $this->callback = di(MiddlewareManager::class)->callerMiddlewares( + return $this->injectMiddleware(); + } + + + /** + * @throws NotFindClassException + * @throws ReflectionException + */ + private function injectMiddleware(): static + { + $manager = di(MiddlewareManager::class); + if ($this->handler instanceof Closure) { + if (!empty($this->middleware)) { + $this->callback = $manager->closureMiddlewares($this->middleware, $this->createDispatch()); + } else { + $this->callback = $this->createDispatch(); + } + } else { + $manager->addMiddlewares($this->handler[0], $this->handler[1], $this->middleware); + $this->callback = $manager->callerMiddlewares( $this->handler[0], $this->handler[1], $this->createDispatch() ); } diff --git a/System/Di/Container.php b/System/Di/Container.php index 55ead113..d0ee89cc 100644 --- a/System/Di/Container.php +++ b/System/Di/Container.php @@ -214,7 +214,7 @@ class Container extends BaseObject * @return mixed * @throws Exception */ - private function propertyInject(ReflectionClass $reflect, $object): mixed + public function propertyInject(ReflectionClass $reflect, $object): mixed { if (!isset(static::$_propertyAttributes[$reflect->getName()])) { return $object; @@ -228,7 +228,7 @@ class Container extends BaseObject /** - * @param \ReflectionClass $class + * @param ReflectionClass $class */ private function resolveMethodAttribute(ReflectionClass $class) { @@ -251,12 +251,11 @@ class Container extends BaseObject } - /** - * @param \ReflectionAttribute $attribute - * @param \ReflectionClass $class - * @param $object - */ - private function setReflectionMethod(ReflectionClass $class, \ReflectionMethod $method) + /** + * @param ReflectionClass $class + * @param ReflectionMethod $method + */ + private function setReflectionMethod(ReflectionClass $class, ReflectionMethod $method) { if (!isset(static::$_attributeMaping[$class->getName()])) { static::$_attributeMaping[$class->getName()] = []; @@ -265,12 +264,12 @@ class Container extends BaseObject } - /** - * @param \ReflectionAttribute $attribute - * @param \ReflectionClass $class - * @param $object - */ - private function setMethodsAttributes(\ReflectionClass $attribute, ReflectionMethod $method, $object) + /** + * @param ReflectionClass $attribute + * @param ReflectionMethod $method + * @param $object + */ + private function setMethodsAttributes(ReflectionClass $attribute, ReflectionMethod $method, $object) { if (!isset(static::$_methodsAttributes[$attribute->getName()])) { static::$_methodsAttributes[$attribute->getName()] = []; @@ -280,7 +279,7 @@ class Container extends BaseObject /** - * @param \ReflectionClass $class + * @param ReflectionClass $class */ private function resolveTargetAttribute(ReflectionClass $class) { @@ -299,7 +298,7 @@ class Container extends BaseObject /** * @param $className * @param $method - * @return \ReflectionMethod|null + * @return ReflectionMethod|null */ public function getReflectionMethod($className, $method): ?ReflectionMethod { @@ -325,9 +324,9 @@ class Container extends BaseObject /** * @param string $class * @param string|null $property - * @return ReflectionProperty|array|null + * @return ReflectionProperty|ReflectionProperty[]|null */ - public function getClassProperty(string $class, string $property = null): ReflectionProperty|null|array + public function getClassReflectionProperty(string $class, string $property = null): ReflectionProperty|null|array { if (!isset(static::$_reflectionProperty[$class])) { return null; diff --git a/System/Snowflake.php b/System/Snowflake.php index cddc6edb..c409fc9e 100644 --- a/System/Snowflake.php +++ b/System/Snowflake.php @@ -56,7 +56,7 @@ class Snowflake */ public static function injectProperty(object $class) { - $attributes = static::getDi()->getClassProperty($class::class); + $attributes = static::getDi()->getClassReflectionProperty($class::class); /** * @var string $property * @var ReflectionProperty $attribute