Commit a6ef32e6 authored by catch's avatar catch
Browse files

Issue #3120301 by alexpott, zestagio, Wim Leers: RoutePreloader: prevent...

Issue #3120301 by alexpott, zestagio, Wim Leers: RoutePreloader: prevent preloading of routes generated by JSON:API
parent 40a123ae
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\KernelEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Route;

/**
 * Defines a class which preloads non-admin routes.
@@ -98,7 +99,7 @@ public function onRequest(KernelEvent $event) {
  public function onAlterRoutes(RouteBuildEvent $event) {
    $collection = $event->getRouteCollection();
    foreach ($collection->all() as $name => $route) {
      if (strpos($route->getPath(), '/admin/') !== 0 && $route->getPath() != '/admin') {
      if (strpos($route->getPath(), '/admin/') !== 0 && $route->getPath() != '/admin' && static::isGetAndHtmlRoute($route)) {
        $this->nonAdminRoutesOnRebuild[] = $name;
      }
    }
@@ -126,4 +127,21 @@ public static function getSubscribedEvents() {
    return $events;
  }

  /**
   * Determines whether the given route is a GET and HTML route.
   *
   * @param \Symfony\Component\Routing\Route $route
   *   The route to analyze.
   *
   * @return bool
   *   TRUE if GET is a valid method and HTML is a valid format for this route.
   */
  protected static function isGetAndHtmlRoute(Route $route) {
    $methods = $route->getMethods() ?: ['GET'];
    // If a route has no explicit format, then HTML is valid.
    // @see \Drupal\Core\Routing\RequestFormatRouteFilter::getAvailableFormats()
    $format = $route->hasRequirement('_format') ? explode('|', $route->getRequirement('_format')) : ['html'];
    return in_array('GET', $methods, TRUE) && in_array('html', $format, TRUE);
  }

}
+17 −2
Original line number Diff line number Diff line
@@ -108,14 +108,29 @@ public function testOnAlterRoutesWithNonAdminRoutes() {
    $route_collection->add('test', new Route('/admin/foo', ['_controller' => 'Drupal\ExampleController']));
    $route_collection->add('test2', new Route('/bar', ['_controller' => 'Drupal\ExampleController']));
    // Non content routes, like ajax callbacks should be ignored.
    $route_collection->add('test3', new Route('/bar', ['_controller' => 'Drupal\ExampleController']));
    $route3 = new Route('/bar', ['_controller' => 'Drupal\ExampleController']);
    $route3->setMethods(['POST']);
    $route_collection->add('test3', $route3);
    // Routes with the option _admin_route set to TRUE will be included.
    $route4 = new Route('/bar', ['_controller' => 'Drupal\ExampleController']);
    $route4->setOption('_admin_route', TRUE);
    $route_collection->add('test4', $route4);
    // Non-HTML routes, like api_json routes should be ignored.
    $route5 = new Route('/bar', ['_controller' => 'Drupal\ExampleController']);
    $route5->setRequirement('_format', 'api_json');
    $route_collection->add('test5', $route5);
    // Routes which include HTML should be included.
    $route6 = new Route('/bar', ['_controller' => 'Drupal\ExampleController']);
    $route6->setRequirement('_format', 'json_api|html');
    $route_collection->add('test6', $route6);

    $event->expects($this->once())
      ->method('getRouteCollection')
      ->will($this->returnValue($route_collection));

    $this->state->expects($this->once())
      ->method('set')
      ->with('routing.non_admin_routes', ['test2', 'test3']);
      ->with('routing.non_admin_routes', ['test2', 'test4', 'test6']);
    $this->preloader->onAlterRoutes($event);
    $this->preloader->onFinishedRoutes(new Event());
  }