routeResolver = $routeResolver ?? new RouteResolver($this->routeCollector); $routeRunner = new RouteRunner($this->routeResolver, $this->routeCollector->getRouteParser(), $this); if (!$middlewareDispatcher) { $middlewareDispatcher = new MiddlewareDispatcher($routeRunner, $this->callableResolver, $container); } else { $middlewareDispatcher->seedMiddlewareStack($routeRunner); } $this->middlewareDispatcher = $middlewareDispatcher; } /** * @return RouteResolverInterface */ public function getRouteResolver(): RouteResolverInterface { return $this->routeResolver; } /** * @return MiddlewareDispatcherInterface */ public function getMiddlewareDispatcher(): MiddlewareDispatcherInterface { return $this->middlewareDispatcher; } /** * @param MiddlewareInterface|string|callable $middleware */ public function add($middleware): self { $this->middlewareDispatcher->add($middleware); return $this; } /** * @param MiddlewareInterface $middleware */ public function addMiddleware(MiddlewareInterface $middleware): self { $this->middlewareDispatcher->addMiddleware($middleware); return $this; } /** * Add the Slim built-in routing middleware to the app middleware stack * * This method can be used to control middleware order and is not required for default routing operation. * * @return RoutingMiddleware */ public function addRoutingMiddleware(): RoutingMiddleware { $routingMiddleware = new RoutingMiddleware( $this->getRouteResolver(), $this->getRouteCollector()->getRouteParser() ); $this->add($routingMiddleware); return $routingMiddleware; } /** * Add the Slim built-in error middleware to the app middleware stack * * @param bool $displayErrorDetails * @param bool $logErrors * @param bool $logErrorDetails * @param LoggerInterface|null $logger * * @return ErrorMiddleware */ public function addErrorMiddleware( bool $displayErrorDetails, bool $logErrors, bool $logErrorDetails, ?LoggerInterface $logger = null ): ErrorMiddleware { $errorMiddleware = new ErrorMiddleware( $this->getCallableResolver(), $this->getResponseFactory(), $displayErrorDetails, $logErrors, $logErrorDetails, $logger ); $this->add($errorMiddleware); return $errorMiddleware; } /** * Add the Slim body parsing middleware to the app middleware stack * * @param callable[] $bodyParsers * * @return BodyParsingMiddleware */ public function addBodyParsingMiddleware(array $bodyParsers = []): BodyParsingMiddleware { $bodyParsingMiddleware = new BodyParsingMiddleware($bodyParsers); $this->add($bodyParsingMiddleware); return $bodyParsingMiddleware; } /** * Run application * * This method traverses the application middleware stack and then sends the * resultant Response object to the HTTP client. * * @param ServerRequestInterface|null $request * @return void */ public function run(?ServerRequestInterface $request = null): void { if (!$request) { $serverRequestCreator = ServerRequestCreatorFactory::create(); $request = $serverRequestCreator->createServerRequestFromGlobals(); } $response = $this->handle($request); $responseEmitter = new ResponseEmitter(); $responseEmitter->emit($response); } /** * Handle a request * * This method traverses the application middleware stack and then returns the * resultant Response object. * * @param ServerRequestInterface $request * @return ResponseInterface */ public function handle(ServerRequestInterface $request): ResponseInterface { $response = $this->middlewareDispatcher->handle($request); /** * This is to be in compliance with RFC 2616, Section 9. * If the incoming request method is HEAD, we need to ensure that the response body * is empty as the request may fall back on a GET route handler due to FastRoute's * routing logic which could potentially append content to the response body * https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4 */ $method = strtoupper($request->getMethod()); if ($method === 'HEAD') { $emptyBody = $this->responseFactory->createResponse()->getBody(); return $response->withBody($emptyBody); } return $response; } }