You are here

class HttpKernel in Zircon Profile 8

Same name and namespace in other branches
  1. 8.0 vendor/symfony/http-kernel/HttpKernel.php \Symfony\Component\HttpKernel\HttpKernel

HttpKernel notifies events to convert a Request object to a Response one.

@author Fabien Potencier <fabien@symfony.com>

Hierarchy

Expanded class hierarchy of HttpKernel

8 files declare their use of HttpKernel
ContainerAwareHttpKernel.php in vendor/symfony/http-kernel/DependencyInjection/ContainerAwareHttpKernel.php
HttpKernelTest.php in vendor/symfony/http-kernel/Tests/HttpKernelTest.php
InlineFragmentRendererTest.php in vendor/symfony/http-kernel/Tests/Fragment/InlineFragmentRendererTest.php
RequestDataCollectorTest.php in vendor/symfony/http-kernel/Tests/DataCollector/RequestDataCollectorTest.php
TestHttpKernel.php in vendor/symfony/http-kernel/Tests/TestHttpKernel.php

... See full list

1 string reference to 'HttpKernel'
core.services.yml in core/core.services.yml
core/core.services.yml
1 service uses HttpKernel
http_kernel.basic in core/core.services.yml
Symfony\Component\HttpKernel\HttpKernel

File

vendor/symfony/http-kernel/HttpKernel.php, line 34

Namespace

Symfony\Component\HttpKernel
View source
class HttpKernel implements HttpKernelInterface, TerminableInterface {
  protected $dispatcher;
  protected $resolver;
  protected $requestStack;

  /**
   * Constructor.
   *
   * @param EventDispatcherInterface    $dispatcher   An EventDispatcherInterface instance
   * @param ControllerResolverInterface $resolver     A ControllerResolverInterface instance
   * @param RequestStack                $requestStack A stack for master/sub requests
   */
  public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null) {
    $this->dispatcher = $dispatcher;
    $this->resolver = $resolver;
    $this->requestStack = $requestStack ?: new RequestStack();
  }

  /**
   * {@inheritdoc}
   */
  public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) {
    $request->headers
      ->set('X-Php-Ob-Level', ob_get_level());
    try {
      return $this
        ->handleRaw($request, $type);
    } catch (\Exception $e) {
      if (false === $catch) {
        $this
          ->finishRequest($request, $type);
        throw $e;
      }
      return $this
        ->handleException($e, $request, $type);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function terminate(Request $request, Response $response) {
    $this->dispatcher
      ->dispatch(KernelEvents::TERMINATE, new PostResponseEvent($this, $request, $response));
  }

  /**
   * @throws \LogicException If the request stack is empty
   *
   * @internal
   */
  public function terminateWithException(\Exception $exception) {
    if (!($request = $this->requestStack
      ->getMasterRequest())) {
      throw new \LogicException('Request stack is empty', 0, $exception);
    }
    $response = $this
      ->handleException($exception, $request, self::MASTER_REQUEST);
    $response
      ->sendHeaders();
    $response
      ->sendContent();
    $this
      ->terminate($request, $response);
  }

  /**
   * Handles a request to convert it to a response.
   *
   * Exceptions are not caught.
   *
   * @param Request $request A Request instance
   * @param int     $type    The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
   *
   * @return Response A Response instance
   *
   * @throws \LogicException       If one of the listener does not behave as expected
   * @throws NotFoundHttpException When controller cannot be found
   */
  private function handleRaw(Request $request, $type = self::MASTER_REQUEST) {
    $this->requestStack
      ->push($request);

    // request
    $event = new GetResponseEvent($this, $request, $type);
    $this->dispatcher
      ->dispatch(KernelEvents::REQUEST, $event);
    if ($event
      ->hasResponse()) {
      return $this
        ->filterResponse($event
        ->getResponse(), $request, $type);
    }

    // load controller
    if (false === ($controller = $this->resolver
      ->getController($request))) {
      throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', $request
        ->getPathInfo()));
    }
    $event = new FilterControllerEvent($this, $controller, $request, $type);
    $this->dispatcher
      ->dispatch(KernelEvents::CONTROLLER, $event);
    $controller = $event
      ->getController();

    // controller arguments
    $arguments = $this->resolver
      ->getArguments($request, $controller);

    // call controller
    $response = call_user_func_array($controller, $arguments);

    // view
    if (!$response instanceof Response) {
      $event = new GetResponseForControllerResultEvent($this, $request, $type, $response);
      $this->dispatcher
        ->dispatch(KernelEvents::VIEW, $event);
      if ($event
        ->hasResponse()) {
        $response = $event
          ->getResponse();
      }
      if (!$response instanceof Response) {
        $msg = sprintf('The controller must return a response (%s given).', $this
          ->varToString($response));

        // the user may have forgotten to return something
        if (null === $response) {
          $msg .= ' Did you forget to add a return statement somewhere in your controller?';
        }
        throw new \LogicException($msg);
      }
    }
    return $this
      ->filterResponse($response, $request, $type);
  }

  /**
   * Filters a response object.
   *
   * @param Response $response A Response instance
   * @param Request  $request  An error message in case the response is not a Response object
   * @param int      $type     The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
   *
   * @return Response The filtered Response instance
   *
   * @throws \RuntimeException if the passed object is not a Response instance
   */
  private function filterResponse(Response $response, Request $request, $type) {
    $event = new FilterResponseEvent($this, $request, $type, $response);
    $this->dispatcher
      ->dispatch(KernelEvents::RESPONSE, $event);
    $this
      ->finishRequest($request, $type);
    return $event
      ->getResponse();
  }

  /**
   * Publishes the finish request event, then pop the request from the stack.
   *
   * Note that the order of the operations is important here, otherwise
   * operations such as {@link RequestStack::getParentRequest()} can lead to
   * weird results.
   *
   * @param Request $request
   * @param int     $type
   */
  private function finishRequest(Request $request, $type) {
    $this->dispatcher
      ->dispatch(KernelEvents::FINISH_REQUEST, new FinishRequestEvent($this, $request, $type));
    $this->requestStack
      ->pop();
  }

  /**
   * Handles an exception by trying to convert it to a Response.
   *
   * @param \Exception $e       An \Exception instance
   * @param Request    $request A Request instance
   * @param int        $type    The type of the request
   *
   * @return Response A Response instance
   *
   * @throws \Exception
   */
  private function handleException(\Exception $e, $request, $type) {
    $event = new GetResponseForExceptionEvent($this, $request, $type, $e);
    $this->dispatcher
      ->dispatch(KernelEvents::EXCEPTION, $event);

    // a listener might have replaced the exception
    $e = $event
      ->getException();
    if (!$event
      ->hasResponse()) {
      $this
        ->finishRequest($request, $type);
      throw $e;
    }
    $response = $event
      ->getResponse();

    // the developer asked for a specific status code
    if ($response->headers
      ->has('X-Status-Code')) {
      $response
        ->setStatusCode($response->headers
        ->get('X-Status-Code'));
      $response->headers
        ->remove('X-Status-Code');
    }
    elseif (!$response
      ->isClientError() && !$response
      ->isServerError() && !$response
      ->isRedirect()) {

      // ensure that we actually have an error response
      if ($e instanceof HttpExceptionInterface) {

        // keep the HTTP status code and headers
        $response
          ->setStatusCode($e
          ->getStatusCode());
        $response->headers
          ->add($e
          ->getHeaders());
      }
      else {
        $response
          ->setStatusCode(500);
      }
    }
    try {
      return $this
        ->filterResponse($response, $request, $type);
    } catch (\Exception $e) {
      return $response;
    }
  }
  private function varToString($var) {
    if (is_object($var)) {
      return sprintf('Object(%s)', get_class($var));
    }
    if (is_array($var)) {
      $a = array();
      foreach ($var as $k => $v) {
        $a[] = sprintf('%s => %s', $k, $this
          ->varToString($v));
      }
      return sprintf('Array(%s)', implode(', ', $a));
    }
    if (is_resource($var)) {
      return sprintf('Resource(%s)', get_resource_type($var));
    }
    if (null === $var) {
      return 'null';
    }
    if (false === $var) {
      return 'false';
    }
    if (true === $var) {
      return 'true';
    }
    return (string) $var;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
HttpKernel::$dispatcher protected property
HttpKernel::$requestStack protected property
HttpKernel::$resolver protected property
HttpKernel::filterResponse private function Filters a response object.
HttpKernel::finishRequest private function Publishes the finish request event, then pop the request from the stack.
HttpKernel::handle public function Handles a Request to convert it to a Response. Overrides HttpKernelInterface::handle 3
HttpKernel::handleException private function Handles an exception by trying to convert it to a Response.
HttpKernel::handleRaw private function Handles a request to convert it to a response.
HttpKernel::terminate public function Terminates a request/response cycle. Overrides TerminableInterface::terminate
HttpKernel::terminateWithException public function @internal
HttpKernel::varToString private function
HttpKernel::__construct public function Constructor. 4
HttpKernelInterface::MASTER_REQUEST constant
HttpKernelInterface::SUB_REQUEST constant