예제 #1
0
 /**
  * @return RequestMatcherInterface|UrlMatcherInterface
  */
 public function getMatcher()
 {
     /* we may not set the context in DynamicRouter::setContext as this
      * would lead to symfony cache warmup problems.
      * a request matcher does not need the request context separately as it
      * can get it from the request.
      */
     if ($this->matcher instanceof RequestContextAwareInterface) {
         $this->matcher->setContext($this->getContext());
     }
     return $this->matcher;
 }
 /**
  * Makes a subrequest to retrieve the default error page.
  *
  * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
  *   The event to process.
  * @param string $url
  *   The path/url to which to make a subrequest for this error message.
  * @param int $status_code
  *   The status code for the error being handled.
  */
 protected function makeSubrequest(GetResponseForExceptionEvent $event, $url, $status_code)
 {
     $request = $event->getRequest();
     $exception = $event->getException();
     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 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'], '%type: @message in %function (line %line of %file).', $error);
     }
 }