StackedKernelPass.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. namespace Drupal\Core\DependencyInjection\Compiler;
  3. use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
  4. use Symfony\Component\DependencyInjection\ContainerBuilder;
  5. use Symfony\Component\DependencyInjection\Reference;
  6. /**
  7. * Provides a compiler pass for stacked HTTP kernels.
  8. *
  9. * Builds the HTTP kernel by collecting all services tagged 'http_middleware'
  10. * and assembling them into a StackedKernel. The middleware with the highest
  11. * priority ends up as the outermost while the lowest priority middleware wraps
  12. * the actual HTTP kernel defined by the http_kernel.basic service.
  13. *
  14. * The 'http_middleware' service tag additionally accepts a 'responder'
  15. * parameter. It should be set to TRUE if many or most requests will be handled
  16. * directly by the middleware. Any underlying middleware and the HTTP kernel are
  17. * then flagged as 'lazy'. As a result those low priority services and their
  18. * dependencies are only initialized if the 'responder' middleware fails to
  19. * generate a response and the request is delegated to the underlying kernel.
  20. *
  21. * In general middlewares should not have heavy dependencies. This is especially
  22. * important for high-priority services which need to run before the internal
  23. * page cache.
  24. *
  25. * An example of a high priority middleware.
  26. * @code
  27. * http_middleware.reverse_proxy:
  28. * class: Drupal\Core\StackMiddleware\ReverseProxyMiddleware
  29. * arguments: ['@settings']
  30. * tags:
  31. * - { name: http_middleware, priority: 300 }
  32. * @endcode
  33. *
  34. * An example of a responder middleware:
  35. * @code
  36. * http_middleware.page_cache:
  37. * class: Drupal\page_cache\StackMiddleware\PageCache
  38. * arguments: ['@cache.render', '@page_cache_request_policy', '@page_cache_response_policy']
  39. * tags:
  40. * - { name: http_middleware, priority: 200, responder: true }
  41. * @endcode
  42. *
  43. * @see \Stack\Builder
  44. */
  45. class StackedKernelPass implements CompilerPassInterface {
  46. /**
  47. * {@inheritdoc}
  48. */
  49. public function process(ContainerBuilder $container) {
  50. if (!$container->hasDefinition('http_kernel')) {
  51. return;
  52. }
  53. $stacked_kernel = $container->getDefinition('http_kernel');
  54. // Return now if this is not a stacked kernel.
  55. if ($stacked_kernel->getClass() !== 'Stack\StackedHttpKernel') {
  56. return;
  57. }
  58. $middlewares = [];
  59. $priorities = [];
  60. $responders = [];
  61. foreach ($container->findTaggedServiceIds('http_middleware') as $id => $attributes) {
  62. $priorities[$id] = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
  63. $middlewares[$id] = $container->getDefinition($id);
  64. $responders[$id] = !empty($attributes[0]['responder']);
  65. }
  66. array_multisort($priorities, SORT_ASC, $middlewares, $responders);
  67. $decorated_id = 'http_kernel.basic';
  68. $middlewares_param = [new Reference($decorated_id)];
  69. $first_responder = array_search(TRUE, array_reverse($responders, TRUE), TRUE);
  70. if ($first_responder) {
  71. $container->getDefinition($decorated_id)->setLazy(TRUE);
  72. }
  73. foreach ($middlewares as $id => $decorator) {
  74. // Prepend a reference to the middlewares container parameter.
  75. array_unshift($middlewares_param, new Reference($id));
  76. // Prepend the inner kernel as first constructor argument.
  77. $arguments = $decorator->getArguments();
  78. array_unshift($arguments, new Reference($decorated_id));
  79. $decorator->setArguments($arguments);
  80. if ($first_responder === $id) {
  81. $first_responder = FALSE;
  82. }
  83. elseif ($first_responder) {
  84. $decorator->setLazy(TRUE);
  85. }
  86. $decorated_id = $id;
  87. }
  88. $arguments = [$middlewares_param[0], $middlewares_param];
  89. $stacked_kernel->setArguments($arguments);
  90. }
  91. }