Verified Commit c10494df authored by Dave Long's avatar Dave Long
Browse files

Issue #3412168 by godotislate, catch, smustgrave, longwave: Add back "final"...

Issue #3412168 by godotislate, catch, smustgrave, longwave: Add back "final" to Drupal\big_pipe\StackMiddleware\ContentLength
parent af726dbf
Loading
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -6,6 +6,8 @@
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\TerminableInterface;

/**
 * Provides a compiler pass for stacked HTTP kernels.
@@ -100,7 +102,14 @@ public function process(ContainerBuilder $container) {
        $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;
+3 −0
Original line number Diff line number Diff line
@@ -53,6 +53,9 @@ public function handle(Request $request, $type = HttpKernelInterface::MAIN_REQUE

  /**
   * {@inheritdoc}
   *
   * phpcs:ignore Drupal.Commenting.FunctionComment.VoidReturn
   * @return void
   */
  public function terminate(Request $request, Response $response) {
    $previous = NULL;
+1 −1
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@
/**
 * Defines a big pipe middleware that removes Content-Length headers.
 */
class ContentLength implements HttpKernelInterface {
final class ContentLength implements HttpKernelInterface {

  /**
   * Constructs a new ContentLength instance.
+57 −0
Original line number Diff line number Diff line
@@ -7,8 +7,13 @@
use Drupal\Core\DependencyInjection\Compiler\StackedKernelPass;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\StackMiddleware\StackedHttpKernel;
use Drupal\Tests\Core\DependencyInjection\Fixture\FinalTestHttpMiddlewareClass;
use Drupal\Tests\Core\DependencyInjection\Fixture\FinalTestNonTerminableHttpMiddlewareClass;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;

/**
 * @coversDefaultClass \Drupal\Core\DependencyInjection\Compiler\StackedKernelPass
@@ -95,6 +100,58 @@ public function testProcessWithHttpKernel() {
    $this->assertSame($kernel->getArguments(), $unprocessed_kernel->getArguments());
  }

  /**
   * Tests that class declared 'final' can be added as http_middleware.
   */
  public function testProcessWithStackedKernelAndFinalHttpMiddleware(): void {
    $stacked_kernel = new Definition(StackedHttpKernel::class);
    $stacked_kernel->setPublic(TRUE);
    $this->containerBuilder->setDefinition('http_kernel', $stacked_kernel);
    $basic_kernel = $this->getMockBuilder(HttpKernel::class)
      ->disableOriginalConstructor()
      ->onlyMethods(['handle', 'terminate'])
      ->getMock();
    $basic_definition = (new Definition($basic_kernel::class))
      ->setPublic(TRUE);
    $this->containerBuilder->setDefinition('http_kernel.basic', $basic_definition);

    // Services tagged 'http_middleware', other than the highest priority
    // middleware that is a responder, is also set as lazy by
    // StackedKernelPass::process(). Add middleware classes declared final and
    // confirm they are interface proxied correctly.
    // @see https://symfony.com/doc/current/service_container/lazy_services.html#interface-proxifying
    $first_responder = $this->getMockBuilder(HttpKernelInterface::class)
      ->getMock();
    $this->containerBuilder->setDefinition('http_kernel.one', (new Definition($first_responder::class))
      ->setPublic(TRUE)
      ->addTag('http_middleware', [
        'priority' => 200,
        'responder' => TRUE,
      ]));
    // First middleware class declared final.
    $this->containerBuilder->setDefinition('http_kernel.two', (new Definition(FinalTestHttpMiddlewareClass::class))
      ->setPublic(TRUE)
      ->addTag('http_middleware', [
        'priority' => 100,
        'responder' => TRUE,
      ]));
    // Second middleware class declared final, this time without implementing
    // TerminableInterface.
    $this->containerBuilder->setDefinition('http_kernel.three', (new Definition(FinalTestNonTerminableHttpMiddlewareClass::class))
      ->setPublic(TRUE)
      ->addTag('http_middleware', [
        'priority' => 50,
        'responder' => TRUE,
      ]));
    $this->stackedKernelPass->process($this->containerBuilder);
    try {
      $this->containerBuilder->get('http_kernel');
    }
    catch (InvalidArgumentException $e) {
      $this->fail($e->getMessage());
    }
  }

  /**
   * Creates a middleware definition.
   *
+30 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Tests\Core\DependencyInjection\Fixture;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\TerminableInterface;

/**
 * Stub of http_middleware class that is declared final.
 */
final class FinalTestHttpMiddlewareClass implements HttpKernelInterface, TerminableInterface {

  /**
   * {@inheritdoc}
   */
  public function handle(Request $request, int $type = self::MAIN_REQUEST, bool $catch = TRUE): Response {
    return new Response();
  }

  /**
   * {@inheritdoc}
   *
   * phpcs:ignore Drupal.Commenting.FunctionComment.VoidReturn
   * @return void
   */
  public function terminate(Request $request, Response $response) {}

}
Loading