The accepted answer may be appropriate for the intended use case of the OP, however, the title of this question is "Routing match everything".
As this is the closest question I've found from searching the interwebs, I'll just share my discovery here on how to accomplish this for SPAs where all paths that start with "/app" need to be redirected to a single route.
In ./my_module/my_module.routing.yml
:
my_module.app:
path: '/app'
defaults:
_controller: '\Drupal\my_module\Controller\App::content'
requirements:
_access: 'TRUE' # Access is handled by app.
In ./my_module/my_module.services.yml
:
my_module.request_subscriber:
class: Drupal\my_module\EventSubscriber\RequestSubscriber
arguments: ['@router.route_provider', '@controller_resolver', '@http_kernel.controller.argument_resolver']
tags:
- { name: event_subscriber }
In ./my_module/src/EventSubscriber/RequestSubscriber.php
:
<?php
namespace Drupal\my_module\EventSubscriber;
use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Routing\RouteProviderInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Class RequestSubscriber.
*/
class RequestSubscriber implements EventSubscriberInterface {
/**
* The Argument Resolver service.
*
* @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface
*/
protected $argumentResolver;
/**
* The Controller Resolver service.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface
*/
protected $controllerResolver;
/**
* The Route Provider service.
*
* @var \Drupal\Core\Routing\RouteProviderInterface
*/
protected $routeProvider;
/**
* RequestSubscriber constructor.
*
* @param \Drupal\Core\Routing\RouteProviderInterface $routeProvider
* @param \Drupal\Core\Controller\ControllerResolverInterface $controllerResolver
* @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argumentResolver
*/
public function __construct(RouteProviderInterface $routeProvider, ControllerResolverInterface $controllerResolver, ArgumentResolverInterface $argumentResolver) {
$this->routeProvider = $routeProvider;
$this->controllerResolver = $controllerResolver;
$this->argumentResolver = $argumentResolver;
}
/**
* The request event handler.
*
* @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
* The event.
*/
public function checkAppRequest(GetResponseEvent $event) {
$request = $event->getRequest();
$path = $request->getPathInfo();
// Redirect all requests that start with "/app" requests to a single
// route. Note: this is necessary because core doesn't have any other
// way to really handle "wildcard/catch all" routes.
if (strpos($path, '/app') === 0
// Ignore CSS/JS (if it reaches here, it means the file doesn't exist).
&& !in_array(substr($path, -3), ['.css', '.js'])
&& !in_array(substr($path, -4), ['.map'])
) {
$route = $this->routeProvider->getRouteByName('my_module.app');
$definition = $route->getDefault('_controller');
$controller = $this->controllerResolver->getControllerFromDefinition($definition, $path);
$arguments = $this->argumentResolver->getArguments($request, $controller);
$response = \call_user_func_array($controller, $arguments);
if ($response instanceof Response) {
// Set the response, necessary so the kernel knows it got something
// which will also prevent any other event handler from running.
$event->setResponse($response);
return;
}
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
// Check for /app requests.
$events[KernelEvents::REQUEST][] = ['checkAppRequest', 1000];
return $events;
}
}
_permission: 'TRUE'
whereas it should be_access: 'TRUE'
. if that is not a typo, it will explain why your route doesn't work._permission
takes an actual permission string – zerolab Jan 10 '17 at 11:51