diff --git a/http-helper/Route/HandlerProviders.php b/http-helper/Route/HandlerProviders.php index 834e9fc4..0b627bd2 100644 --- a/http-helper/Route/HandlerProviders.php +++ b/http-helper/Route/HandlerProviders.php @@ -19,7 +19,7 @@ class HandlerProviders extends BaseObject * @param $method * @return mixed */ - public static function get($path, $method): mixed + public static function get($path, $method): ?Pipeline { return static::$handlers[$method][$path] ?? null; } diff --git a/http-helper/Route/MiddlewareManager.php b/http-helper/Route/MiddlewareManager.php index e24188ac..3a3f4501 100644 --- a/http-helper/Route/MiddlewareManager.php +++ b/http-helper/Route/MiddlewareManager.php @@ -16,91 +16,112 @@ use Kiri\Abstracts\BaseObject; class MiddlewareManager extends BaseObject { - private static array $_middlewares = []; + private static array $_middlewares = []; - /** - * @param $class - * @param $method - * @param array|string $middlewares - */ - public static 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 static 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($middleware, 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($middleware, static::$_middlewares[$class . '::' . $method])) { + continue; + } + static::$_middlewares[$class . '::' . $method][] = $middleware; + } + } - /** - * @param $class - * @param $method - * @return bool - */ - public static function hasMiddleware($class, $method): bool - { - if (is_object($class)) { - $class = $class::class; - } - return isset(static::$_middlewares[$class . '::' . $method]); - } + /** + * @param $handler + * @return mixed|null + */ + public static function get($handler) + { + if ($handler instanceof Closure) { + return null; + } + [$class, $method] = [$handler[0]::class, $handler[1]]; + if (!static::hasMiddleware($class, $method)) { + return null; + } + return static::$_middlewares[$class . '::' . $method]; + } - /** - * @param $class - * @param $method - * @param $caller - * @return mixed - */ - public static 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 MiddlewareInterface) { - return $pipe->onHandler($passable, $stack); - } - return call_user_func($pipe, $passable, $stack); - }; - }, $caller); - } + /** + * @param $class + * @param $method + * @return bool + */ + public static function hasMiddleware($class, $method): bool + { + if (is_object($class)) { + $class = $class::class; + } + return isset(static::$_middlewares[$class . '::' . $method]); + } - /** - * @param $middlewares - * @param Closure $caller - * @return Closure - */ - public static function closureMiddlewares($middlewares, Closure $caller): Closure - { - return array_reduce(array_reverse($middlewares), function ($stack, $pipe) { - return function ($passable) use ($stack, $pipe) { - if ($pipe instanceof MiddlewareInterface) { - return $pipe->onHandler($passable, $stack); - } - return call_user_func($pipe, $passable, $stack); - }; - }, $caller); - } + /** + * @param $class + * @param $method + * @param $caller + * @return mixed + */ + public static 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 MiddlewareInterface) { + $pipe = [$pipe, 'onHandler']; + } + return call_user_func($pipe, $passable, $stack); + }; + }, $caller); + } + + + /** + * @param $middlewares + * @param Closure $caller + * @return Closure + */ + public static function closureMiddlewares($middlewares, Closure $caller): Closure + { + if (empty($middlewares)) { + return $caller; + } + return array_reduce(array_reverse($middlewares), function ($stack, $pipe) { + return function ($passable) use ($stack, $pipe) { + if ($pipe instanceof MiddlewareInterface) { + $pipe = [$pipe, 'onHandler']; + } + return call_user_func($pipe, $passable, $stack); + }; + }, $caller); + } + } diff --git a/http-helper/Route/Node.php b/http-helper/Route/Node.php index cb49a7ae..3b26e122 100644 --- a/http-helper/Route/Node.php +++ b/http-helper/Route/Node.php @@ -161,64 +161,16 @@ class Node */ private function injectMiddleware(string $method, $handler, $_injectParameters): void { - if (!($handler instanceof Closure)) { - $callback = $this->injectControllerMiddleware($method, $handler, $_injectParameters); - } else { - $callback = $this->injectClosureMiddleware($method, $handler, $_injectParameters); - } + $callback = (new Pipeline())->overall($this->router->getMiddleware()) + ->through($this->middleware[$method] ?? []) + ->through(MiddlewareManager::get($handler)) + ->send($_injectParameters) + ->then($handler); + HandlerProviders::add($method, $this->sourcePath, $callback); } - /** - * @param $method - * @param $handler - * @param $_injectParameters - * @return mixed - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - private function injectControllerMiddleware($method, $handler, $_injectParameters): mixed - { - $middleware = $this->middleware[$method] ?? []; - - $allowMiddleware = $this->router->getMiddleware(); - if (!empty($allowMiddleware)) { - array_unshift($middleware, $allowMiddleware); - } - MiddlewareManager::addMiddlewares($handler[0], $handler[1], $middleware); - return MiddlewareManager::callerMiddlewares( - $handler[0], $handler[1], $this->aopHandler($this->getAop($handler), $handler, $_injectParameters) - ); - } - - - /** - * @param $method - * @param $handler - * @param $_injectParameters - * @return Closure - * @throws Exception - */ - private function injectClosureMiddleware($method, $handler, $_injectParameters): Closure - { - $middleware = $this->middleware[$method] ?? []; - - $allowMiddleware = $this->router->getMiddleware(); - if (!empty($allowMiddleware)) { - array_unshift($middleware, $allowMiddleware); - } - if (!empty($middleware)) { - return MiddlewareManager::closureMiddlewares($middleware, - $this->normalHandler($handler, $_injectParameters) - ); - } else { - return $this->normalHandler($handler, $_injectParameters); - } - } - - /** * @throws ReflectionException * @throws NotFindClassException @@ -236,56 +188,6 @@ class Node } - /** - * @param IAspect|null $reflect - * @param $handler - * @param $_injectParameters - * @return Closure - */ - #[Pure] private function aopHandler(?IAspect $reflect, $handler, $_injectParameters): Closure - { - if (is_null($reflect)) { - return $this->normalHandler($handler, $_injectParameters); - } - return static function () use ($reflect, $handler, $_injectParameters) { - return $reflect->invoke($handler, $_injectParameters); - }; - } - - - /** - * @throws ReflectionException|NotFindClassException - */ - private function getAop($handler): ?IAspect - { - [$controller, $action] = $handler; - - if (is_object($controller)) { - $controller = get_class($controller); - } - - /** @var Aspect $aspect */ - $aspect = NoteManager::getSpecify_annotation(Aspect::class, $controller, $action); - if (empty($aspect)) { - return null; - } - return di($aspect->aspect); - } - - - /** - * @param $handler - * @param $_injectParameters - * @return Closure - */ - private function normalHandler($handler, $_injectParameters): Closure - { - return static function () use ($handler, $_injectParameters) { - return call_user_func($handler, ...$_injectParameters); - }; - } - - /** * @return array */ @@ -427,7 +329,7 @@ class Node if (empty($handlerProviders)) { throw new RequestException('

HTTP 404 Not Found


Powered by Swoole', 404); } - return call_user_func($handlerProviders, request()); + return $handlerProviders->interpreter(); } } diff --git a/http-helper/Route/Pipeline.php b/http-helper/Route/Pipeline.php new file mode 100644 index 00000000..4498eddc --- /dev/null +++ b/http-helper/Route/Pipeline.php @@ -0,0 +1,172 @@ +passable = $passable; + return $this; + } + + + /** + * @param $middle + * @return $this + */ + public function overall($middle): static + { + $this->overall = $middle; + return $this; + } + + + /** + * 调用栈 + * @param $pipes + * @return $this + */ + public function through($pipes) + { + if (empty($this->pipes)) { + $this->pipes = is_array($pipes) ? $pipes : func_get_args(); + } else { + foreach ($pipes as $pipe) { + $this->pipes[] = $pipe; + } + } + return $this; + } + + /** + * 执行 + * @param Closure $destination + * @return mixed + */ + public function then(callable $destination) + { + $parameters = $this->passable; + if (!empty($this->overall)) { + array_unshift($this->pipes, $this->overall); + } + if (is_array($destination)) { + $destination = $this->aspect_caller($destination, $parameters); + } + $this->pipeline = array_reduce(array_reverse($this->pipes), $this->carry(), + static function () use ($destination, $parameters) { + return call_user_func($destination, ...$parameters); + } + ); + return $this->clear(); + } + + + /** + * @return $this + */ + private function clear() + { + $this->pipes = []; + $this->passable = null; + $this->overall = null; + return $this; + } + + + /** + * @param $destination + * @param $parameters + * @return \Closure + */ + private function aspect_caller($destination, $parameters) + { + [$controller, $action] = $destination; + /** @var \Annotation\Aspect $aop */ + $aop = NoteManager::getSpecify_annotation(Aspect::class, $controller::class, $action); + if (!empty($aop)) { + $aop = Kiri::getDi()->get($aop->aspect); + $destination = static function () use ($aop, $destination, $parameters) { + /** @var \Kiri\IAspect $aop */ + $aop->invoke($destination, $parameters); + }; + } + return $destination; + } + + + /** + * @return mixed + */ + public function interpreter(): mixed + { + return call_user_func($this->pipeline, request()); + } + + + /** + * 设置异常处理器 + * @param callable $handler + * @return $this + */ + public function whenException($handler) + { + $this->exceptionHandler = $handler; + return $this; + } + + + /** + * @return \Closure + */ + protected function carry(): Closure + { + return static function ($stack, $pipe) { + return static function ($passable) use ($stack, $pipe) { + if ($pipe instanceof MiddlewareInterface) { + $pipe = [$pipe, 'OnHandler']; + } + return $pipe($passable, $stack); + }; + }; + } + + /** + * 异常处理 + * @param $passable + * @param $e + * @return mixed + * @throws \Throwable + */ + protected function handleException($passable, Throwable $e) + { + if ($this->exceptionHandler) { + return call_user_func($this->exceptionHandler, $passable, $e); + } + throw $e; + } + +}