function DefaultExceptionHtmlSubscriber::makeSubrequest

Same name in other branches
  1. 9 core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php \Drupal\Core\EventSubscriber\DefaultExceptionHtmlSubscriber::makeSubrequest()
  2. 8.9.x core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php \Drupal\Core\EventSubscriber\DefaultExceptionHtmlSubscriber::makeSubrequest()
  3. 11.x core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php \Drupal\Core\EventSubscriber\DefaultExceptionHtmlSubscriber::makeSubrequest()

Makes a subrequest to retrieve the default error page.

Parameters

\Symfony\Component\HttpKernel\Event\ExceptionEvent $event: The event to process.

string $url: The path/url to which to make a subrequest for this error message.

int $status_code: The status code for the error being handled.

5 calls to DefaultExceptionHtmlSubscriber::makeSubrequest()
CustomPageExceptionHtmlSubscriber::makeSubrequestToCustomPath in core/lib/Drupal/Core/EventSubscriber/CustomPageExceptionHtmlSubscriber.php
Makes a subrequest to retrieve the custom error page.
DefaultExceptionHtmlSubscriber::on401 in core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php
Handles a 401 error for HTML.
DefaultExceptionHtmlSubscriber::on403 in core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php
Handles a 403 error for HTML.
DefaultExceptionHtmlSubscriber::on404 in core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php
Handles a 404 error for HTML.
DefaultExceptionHtmlSubscriber::on4xx in core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php
Handles a 4xx error for HTML.

File

core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php, line 135

Class

DefaultExceptionHtmlSubscriber
Exception subscriber for handling core default HTML error pages.

Namespace

Drupal\Core\EventSubscriber

Code

protected function makeSubrequest(ExceptionEvent $event, $url, $status_code) {
    $request = $event->getRequest();
    $exception = $event->getThrowable();
    try {
        // Reuse the exact same request (so keep the same URL, keep the access
        // result, the exception, et cetera) but override the routing information.
        // This means that aside from routing, this is identical to the master
        // request. This allows us to generate a response that is executed on
        // behalf of the master request, i.e. for the original URL. This is what
        // allows us to e.g. generate a 404 response for the original URL; if we
        // would execute a subrequest with the 404 route's URL, then it'd be
        // generated for *that* URL, not the *original* URL.
        $sub_request = clone $request;
        // The routing to the 404 page should be done as GET request because it is
        // restricted to GET and POST requests only. Otherwise a DELETE request
        // would for example trigger a method not allowed exception.
        $request_context = clone $this->accessUnawareRouter
            ->getContext();
        $request_context->setMethod('GET');
        $this->accessUnawareRouter
            ->setContext($request_context);
        $sub_request->attributes
            ->add($this->accessUnawareRouter
            ->match($url));
        // Add to query (GET) or request (POST) parameters:
        // - 'destination' (to ensure e.g. the login form in a 403 response
        //   redirects to the original URL)
        // - '_exception_statuscode'
        $parameters = $sub_request->isMethod('GET') ? $sub_request->query : $sub_request->request;
        $parameters->add($this->redirectDestination
            ->getAsArray() + [
            '_exception_statuscode' => $status_code,
        ]);
        $response = $this->httpKernel
            ->handle($sub_request, HttpKernelInterface::SUB_REQUEST);
        // Only 2xx responses should have their status code overridden; any
        // other status code should be passed on: redirects (3xx), error (5xx)…
        // @see https://www.drupal.org/node/2603788#comment-10504916
        if ($response->isSuccessful()) {
            $response->setStatusCode($status_code);
        }
        // Persist the exception's cacheability metadata, if any. If the exception
        // itself isn't cacheable, then this will make the response uncacheable:
        // max-age=0 will be set.
        if ($response instanceof CacheableResponseInterface) {
            $response->addCacheableDependency($exception);
        }
        // Persist any special HTTP headers that were set on the exception.
        if ($exception instanceof HttpExceptionInterface) {
            $response->headers
                ->add($exception->getHeaders());
        }
        $event->setResponse($response);
    } catch (\Exception $e) {
        // If an error happened in the subrequest we can't do much else. Instead,
        // just log it. The DefaultExceptionSubscriber will catch the original
        // exception and handle it normally.
        $error = Error::decodeException($e);
        $this->logger
            ->log($error['severity_level'], Error::DEFAULT_ERROR_MESSAGE, $error);
    }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.