router = $router; $this->app = $app; } public function dispatch(Request $request): Response { Request::setCurrent($request); try { $route = $this->router->match($request->method(), $request->path()); if (!$route) { return Response::notFound('Page not found.'); } if ($route->getMiddleware() !== null) { $early = $this->runMiddleware($route->getMiddleware(), $request, $route->getRequiredPermission()); if ($early !== null) { return $early; } } $result = $route->dispatch($this->app); return $this->normalizeResponse($result); } catch (Throwable $e) { return Response::serverError($e->getMessage()); } finally { Request::clearCurrent(); } } protected function runMiddleware(string $name, Request $request, ?string $permission): ?Response { return match ($name) { 'auth' => (new AuthMiddleware())->handle($request, $permission), default => null, }; } protected function normalizeResponse(mixed $result): Response { if ($result instanceof Response) { return $result; } if (is_array($result)) { return Response::json($result); } return new Response((string) $result); } }