From 0341d86d6a7a897c9ca1b3670c50e0094111782b Mon Sep 17 00:00:00 2001 From: tbreuss Date: Sat, 8 Sep 2018 11:24:54 +0200 Subject: [PATCH] Cleaner & better middleware implementation --- src/Application.php | 21 ++--- src/Middleware/MiddlewareDispatcher.php | 51 ----------- src/Middleware/MiddlewarePipe.php | 60 +++++++++++++ src/Middleware/MiddlewareStack.php | 87 +++++++++++++++++++ ...outerMiddleware.php => RequestHandler.php} | 14 +-- 5 files changed, 159 insertions(+), 74 deletions(-) delete mode 100644 src/Middleware/MiddlewareDispatcher.php create mode 100644 src/Middleware/MiddlewarePipe.php create mode 100644 src/Middleware/MiddlewareStack.php rename src/Middleware/{RouterMiddleware.php => RequestHandler.php} (93%) diff --git a/src/Application.php b/src/Application.php index 2391753..f26447e 100644 --- a/src/Application.php +++ b/src/Application.php @@ -7,10 +7,9 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; -use Tebe\HttpFactory\HttpFactory; use Tebe\Pvc\Exception\SystemException; -use Tebe\Pvc\Middleware\MiddlewareDispatcher; -use Tebe\Pvc\Middleware\RouterMiddleware; +use Tebe\Pvc\Middleware\MiddlewarePipe; +use Tebe\Pvc\Middleware\RequestHandler; class Application { @@ -175,20 +174,10 @@ public function run(): void $view = new View($viewsPath); $this->setView($view); - $middlewares = array_merge( - $this->middlewares, - [new RouterMiddleware($this->getView(), $this->getConfig()->get('controllersPath'))] - ); - - $middlewareDispatcher = new MiddlewareDispatcher( - $middlewares, - function () { - return (new HttpFactory)->createResponse(200); - } - ); - + $pipe = MiddlewarePipe::create($this->middlewares); $request = $this->getRequest(); - $response = $middlewareDispatcher->handle($request); + $requestHandler = new RequestHandler($view, $this->getConfig()->get('controllersPath')); + $response = $pipe->process($request, $requestHandler); $this->emit($response); } diff --git a/src/Middleware/MiddlewareDispatcher.php b/src/Middleware/MiddlewareDispatcher.php deleted file mode 100644 index 1c22adf..0000000 --- a/src/Middleware/MiddlewareDispatcher.php +++ /dev/null @@ -1,51 +0,0 @@ -middlewares = $middlewares; - $this->default = $default; - } - - /** - * @param ServerRequestInterface $request - * @return ResponseInterface - */ - public function handle(ServerRequestInterface $request): ResponseInterface - { - $middleware = array_shift($this->middlewares); - - // It there's no middleware use the default callable - if ($middleware === null) { - return call_user_func($this->default, $request); - } - - return $middleware->process($request, $this); - } -} diff --git a/src/Middleware/MiddlewarePipe.php b/src/Middleware/MiddlewarePipe.php new file mode 100644 index 0000000..a5f3725 --- /dev/null +++ b/src/Middleware/MiddlewarePipe.php @@ -0,0 +1,60 @@ +add($middleware); + } + return $pipe; + } + + /** + * @param ServerRequestInterface $request + * @param RequestHandlerInterface $requestHandler + * @return ResponseInterface + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $requestHandler): ResponseInterface + { + if (empty($this->middlewares)) { + return $requestHandler->handle($request); + } + $stack = MiddlewareStack::create($requestHandler, array_reverse($this->middlewares)); + return $stack->handle($request); + } + + /** + * Creates a new pipe with the given middleware connected. + * + * @param MiddlewareInterface $middleware + * @return self + */ + public function add(MiddlewareInterface $middleware): self + { + $pipe = clone $this; + array_push($pipe->middlewares, $middleware); + return $pipe; + } +} diff --git a/src/Middleware/MiddlewareStack.php b/src/Middleware/MiddlewareStack.php new file mode 100644 index 0000000..f63b091 --- /dev/null +++ b/src/Middleware/MiddlewareStack.php @@ -0,0 +1,87 @@ +requestHandler = $requestHandler; + } + + /** + * @param RequestHandlerInterface $requestHandler + * @param MiddlewareInterface[] $middlewares LIFO array of middlewares + * @return self + */ + public static function create(RequestHandlerInterface $requestHandler, array $middlewares = []): self + { + $stack = new self($requestHandler); + foreach ($middlewares as $middleware) { + $stack = $stack->push($middleware); + } + return $stack; + } + + /** + * @param ServerRequestInterface $request + * @return ResponseInterface + */ + public function handle(ServerRequestInterface $request): ResponseInterface + { + $next = $this->peek(); + if (null === $next) { + return $this->requestHandler->handle($request); + } + return $next->process($request, $this->pop()); + } + + /** + * Creates a new stack with the given middleware pushed. + * + * @param MiddlewareInterface $middleware + * @return self + */ + public function push(MiddlewareInterface $middleware): self + { + $stack = clone $this; + array_unshift($stack->middlewares, $middleware); + return $stack; + } + + /** + * @return MiddlewareInterface|null + */ + private function peek() + { + return reset($this->middlewares) ?: null; + } + + /** + * @return self + */ + private function pop(): self + { + $stack = clone $this; + array_shift($stack->middlewares); + return $stack; + } +} diff --git a/src/Middleware/RouterMiddleware.php b/src/Middleware/RequestHandler.php similarity index 93% rename from src/Middleware/RouterMiddleware.php rename to src/Middleware/RequestHandler.php index e2af8eb..33bcbb1 100644 --- a/src/Middleware/RouterMiddleware.php +++ b/src/Middleware/RequestHandler.php @@ -6,15 +6,15 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; +use Tebe\HttpFactory\HttpFactory; use Tebe\Pvc\Controller; use Tebe\Pvc\ErrorController; use Tebe\Pvc\Exception\HttpException; use Tebe\Pvc\Exception\SystemException; use Tebe\Pvc\View; -class RouterMiddleware implements MiddlewareInterface +class RequestHandler implements RequestHandlerInterface { /** * @var View @@ -35,6 +35,7 @@ class RouterMiddleware implements MiddlewareInterface * RouterMiddleware constructor. * @param View $view * @param string $controllersPath + * @throws SystemException */ public function __construct(View $view, string $controllersPath) { @@ -43,14 +44,12 @@ public function __construct(View $view, string $controllersPath) } /** - * @param ServerRequestInterface $request - * @param RequestHandlerInterface $handler - * @return ResponseInterface + * Handle the request and return a response. */ - public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + public function handle(ServerRequestInterface $request): ResponseInterface { $this->request = $request; - $response = $handler->handle($request); + $response = (new HttpFactory())->createResponse(); $pathInfo = $this->getPathInfo(); try { @@ -129,6 +128,7 @@ private function executeAction(Controller $controller): string * @param Controller $controller * @param string $methodName * @return array + * @throws \ReflectionException */ private function getHttpGetVars(Controller $controller, string $methodName): array {