0

I'm pretty confused by this.

I am experimenting with using an HTTP middleware to try to send Google Analytics page views from the server instead of the client.

However, after adding a basic middleware, I'm getting the following error:

Circular reference detected for service "http_kernel", path: "jsonapi.file_upload -> http_kernel -> http_middleware.negotiation -> http_middleware.reverse_proxy -> http_middleware.page_cache -> http_middle ware.kernel_pre_handle -> http_middleware.session -> MYMODULE.analytics_middleware".

In services.yml:

  MYMODULE.analytics_middleware:
    class: Drupal\MYMODULE\Middleware\MyModuleAnalytics
    arguments: ['@http_kernel', '@path.current', '@logger.factory' ]
    tags:
      - { name: http_middleware, priority: 180, responder: true }

MyModuleAnalytics.php:

class MyModuleAnalytics implements HttpKernelInterface {
  /**
   * The wrapped HTTP kernel.
   *
   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
   */
  protected $httpKernel;

  /**
   * The current path.
   *
   * @var \Drupal\Core\Path\CurrentPathStack
   */
  protected $currentPath;

  /**
   * Logger factory.
   *
   * @var \Drupal\Core\Logger\LoggerChannelInterface
   */
  protected LoggerChannelInterface $loggerFactory;

  /**
   * Creates a HTTP middleware handler.
   *
   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $kernel
   *   The HTTP kernel.
   */
  public function __construct(HttpKernelInterface $kernel, CurrentPathStack $current_path, LoggerChannelFactoryInterface $logger_factory) {
    $this->httpKernel = $kernel;
    $this->currentPath = $current_path;
    $this->loggerFactory = $logger_factory->get(MyModuleLoggerChannel::Analytics->value);
  }

  /**
   * {@inheritdoc}
   */
  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
    // Custom logic goes here.
    $current_path = $this->currentPath->getPath();
    $this->loggerFactory->info("Current path: $current_path");

    return $this->httpKernel->handle($request, $type, $catch);
  }

I can remove the circular error by removing the @http_kernel argument in services.yml:

  MYMODULE.analytics_middleware:
    class: Drupal\MYMODULE\Middleware\MyModuleAnalytics
    arguments: ['@path.current', '@logger.factory' ]
    tags:
      - { name: http_middleware, priority: 180, responder: true }

However, PHPStorm complains because the number of arguments are wrong. (But the site loads and the logger functions correctly, so maybe it's ok...?) The documentation states:

The Drupal\Core\DependencyInjection\Compiler\StackedKernelPass compiler pass implicitly prepends the inner kernel as first constructor argument of the middleware. Thus, you do not need to define arguments in your modules *.services.yml definition for the middleware unless your middleware depends on another registered service.

Does this mean I should never pass @http_kernel to the middleware? Because the wording suggests to me that "you do not need to include the argument if it is the only argument, but if there are multiple arguments, you should include them all."

What is the correct way to pass arguments to a middleware service?

1 Answer 1

1

The kernels are stacked, so you can't add the kernel as container argument, this results in a circular reference. Only the compiler pass can determine the inner kernel, which the outer middleware has to invoke if it doesn't return a response.

The IDE looks at the static container, it can't tell what compiler passes are adding to the service arguments, unless there is an IDE plugin adding a little extra intelligence.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.