class StackedKernelPass

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/DependencyInjection/Compiler/StackedKernelPass.php \Drupal\Core\DependencyInjection\Compiler\StackedKernelPass
  2. 8.9.x core/lib/Drupal/Core/DependencyInjection/Compiler/StackedKernelPass.php \Drupal\Core\DependencyInjection\Compiler\StackedKernelPass
  3. 10 core/lib/Drupal/Core/DependencyInjection/Compiler/StackedKernelPass.php \Drupal\Core\DependencyInjection\Compiler\StackedKernelPass

Provides a compiler pass for stacked HTTP kernels.

Builds the HTTP kernel by collecting all services tagged 'http_middleware' and assembling them into a StackedHttpKernel. The middleware with the highest priority ends up as the outermost while the lowest priority middleware wraps the actual HTTP kernel defined by the http_kernel.basic service.

The 'http_middleware' service tag additionally accepts a 'responder' parameter. It should be set to TRUE if many or most requests will be handled directly by the middleware. Any underlying middleware and the HTTP kernel are then flagged as 'lazy'. As a result those low priority services and their dependencies are only initialized if the 'responder' middleware fails to generate a response and the request is delegated to the underlying kernel.

In general middlewares should not have heavy dependencies. This is especially important for high-priority services which need to run before the internal page cache.

An example of a high priority middleware.


http_middleware.reverse_proxy:
  class: Drupal\Core\StackMiddleware\ReverseProxyMiddleware
  arguments: ['@settings']
  tags:
    - { name: http_middleware, priority: 300 }

An example of a responder middleware:


http_middleware.page_cache:
  class: Drupal\page_cache\StackMiddleware\PageCache
  arguments: ['@cache.render', '@page_cache_request_policy', '@page_cache_response_policy']
  tags:
    - { name: http_middleware, priority: 200, responder: true }

Hierarchy

  • class \Drupal\Core\DependencyInjection\Compiler\StackedKernelPass implements \Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface

Expanded class hierarchy of StackedKernelPass

See also

\Drupal\Core\StackMiddleware\StackedHttpKernel

2 files declare their use of StackedKernelPass
CoreServiceProvider.php in core/lib/Drupal/Core/CoreServiceProvider.php
StackedKernelPassTest.php in core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/StackedKernelPassTest.php

File

core/lib/Drupal/Core/DependencyInjection/Compiler/StackedKernelPass.php, line 51

Namespace

Drupal\Core\DependencyInjection\Compiler
View source
class StackedKernelPass implements CompilerPassInterface {
    
    /**
     * {@inheritdoc}
     */
    public function process(ContainerBuilder $container) : void {
        if (!$container->hasDefinition('http_kernel')) {
            return;
        }
        $stacked_kernel = $container->getDefinition('http_kernel');
        // Return now if this is not a stacked kernel.
        if ($stacked_kernel->getClass() !== StackedHttpKernel::class) {
            return;
        }
        $middlewares = [];
        $priorities = [];
        $responders = [];
        foreach ($container->findTaggedServiceIds('http_middleware') as $id => $attributes) {
            $priorities[$id] = $attributes[0]['priority'] ?? 0;
            $middlewares[$id] = $container->getDefinition($id);
            $responders[$id] = !empty($attributes[0]['responder']);
        }
        array_multisort($priorities, SORT_ASC, $middlewares, $responders);
        $decorated_id = 'http_kernel.basic';
        $middlewares_param = [
            new Reference($decorated_id),
        ];
        $first_responder = array_search(TRUE, array_reverse($responders, TRUE), TRUE);
        if ($first_responder) {
            $container->getDefinition($decorated_id)
                ->setLazy(TRUE);
        }
        foreach ($middlewares as $id => $decorator) {
            // Prepend a reference to the middlewares container parameter.
            array_unshift($middlewares_param, new Reference($id));
            // Prepend the inner kernel as first constructor argument.
            $arguments = $decorator->getArguments();
            array_unshift($arguments, new Reference($decorated_id));
            $decorator->setArguments($arguments);
            if ($first_responder === $id) {
                $first_responder = FALSE;
            }
            elseif ($first_responder) {
                // Use interface proxying to allow middleware classes declared final
                // to be set as lazy.
                $decorator->setLazy(TRUE);
                foreach ([
                    HttpKernelInterface::class,
                    TerminableInterface::class,
                ] as $interface) {
                    if (is_a($decorator->getClass(), $interface, TRUE)) {
                        $decorator->addTag('proxy', [
                            'interface' => $interface,
                        ]);
                    }
                }
            }
            $decorated_id = $id;
        }
        $arguments = [
            $middlewares_param[0],
            $middlewares_param,
        ];
        $stacked_kernel->setArguments($arguments);
    }

}

Members

Title Sort descending Modifiers Object type Summary
StackedKernelPass::process public function

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