Updated: Comment #N

Problem/Motivation

The \Symfony\Component\HttpKernel\EventListener\RouterListener operates in two modes (according to the doxygen comments of the class):

  • 2.3 compatibility mode where you must call setRequest whenever the Request changes.
  • 2.4+ mode where you must pass a RequestStack instance in the constructor.

When operating in 2.4+ mode, the router listener updates the request context from within its KernelEvents::REQUEST event handler. This allows us to decouple the router.request_context service from the request service.

Proposed resolution

Decouple router.request_context from request service and instead let router_listener update the request context for us.

Remaining tasks

User interface changes

API changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

znerol’s picture

Status: Active » Needs review
FileSize
6.13 KB

Status: Needs review » Needs work

The last submitted patch, 1: 2223593-use-request-stack-in-router.diff, failed testing.

znerol’s picture

Status: Needs work » Needs review
FileSize
6.09 KB

Reroll after #1316692: Convert hook_admin_paths() into declarative properties on routes. How do we educate devs to use request stack service instead of request service in new code?

Status: Needs review » Needs work

The last submitted patch, 3: 2223593-use-request-stack-in-router-2.diff, failed testing.

znerol’s picture

Supposedly the test failures are a result of working with the url generator lacking an appropriate request object in the parent site. As a consequence the global url function might produce different results for the parent site and the child site.

Therefore it may be necessary to setup the request stack in the simpletest parent site, such that a proper request is available through the request_stack service.

znerol’s picture

The natural place to inject the request-context into the test-container would be either TestBase::rebuildContainer or WebTestBase::prepareRequestForGenerator. However none of them works because further down in setUp we're calling drupal_flush_all_caches and that one ends up in DrupalKernel::boot(). In fact DrupalKernel::updateModules() reboots the kernel for the reason stated in the following comment:

    // If we haven't yet booted, we don't need to do anything: the new module
    // list will take effect when boot() is called. If we have already booted,
    // then reboot in order to refresh the serviceProvider list and container.
core/lib/Drupal/Core/DrupalKernel.php.Drupal\Core\DrupalKernel->initializeContainer() : lineno 379	
core/lib/Drupal/Core/DrupalKernel.php.Drupal\Core\DrupalKernel->boot() : lineno 177	
core/lib/Drupal/Core/DrupalKernel.php.Drupal\Core\DrupalKernel->updateModules() : lineno 338	
core/includes/common.inc.drupal_flush_all_caches() : lineno 4937	
core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php.Drupal\simpletest\WebTestBase->resetAll() : lineno 1029	
core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php.Drupal\simpletest\WebTestBase->setUp() : lineno 872	
core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTestBase.php.Drupal\taxonomy\Tests\TaxonomyTestBase->setUp() : lineno 26	
core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php.Drupal\taxonomy\Tests\TokenReplaceTest->setUp() : lineno 28	
core/modules/simpletest/lib/Drupal/simpletest/TestBase.php.Drupal\simpletest\TestBase->run() : lineno 858	
[...]

The reason why the $request service is not affected, is that the kernel takes care of restoring it when rebuilding the container. We probably need to do the same for request-context.

I think that the proper way to resolve the problem would be to delay booting the kernel until after WebTestBase::resetAll. However, that does not seem practical given that a lot of services are accessed throughout WebTestBase::setUp.

znerol’s picture

Status: Needs work » Needs review
FileSize
9.6 KB
3.51 KB

Let's try that.

znerol’s picture

FileSize
8.97 KB

@dawehner questions the hunk in WebTestBase::prepareRequestForGenerator. Let's see whether we can live without it.

znerol’s picture

Get rid of custom persist logic for the router.request_context</service>. The custom logic actually is only required for the <code>request service because it potentially is scoped.

Persisting router.request_context service actually is necessary because the reasons given in #6: In short we end up with an empty request context and that will affect the URL generator (and thus the url function) in the simpletest parent.

znerol’s picture

FileSize
7.32 KB
znerol’s picture

FileSize
2.43 KB

The change to Symfony\Cmf\Component\Routing\ProviderBasedGenerator was accidental. Lets revert that and at the same time revert the changes to the Drupal\Core\Routing\UrlGenerator to restore consistency with CMF.

Status: Needs review » Needs work

The last submitted patch, 11: 2223593-use-request-stack-in-router-10.diff, failed testing.

znerol’s picture

FileSize
2.43 KB

Silly me, failed to add the '@'-character to one of the container service references.

znerol’s picture

Status: Needs work » Needs review
znerol’s picture

Title: Use request stack in route listener / matcher / url generator » Decouple the router.request_context service from the request service.
znerol’s picture

Reroll, no changes.

znerol’s picture

znerol’s picture

dawehner’s picture

Status: Needs review » Reviewed & tested by the community
+++ b/core/core.services.yml
@@ -306,7 +306,7 @@ services:
-      - [setContext, ['@?router.request_context']]
+      - [setContext, ['@router.request_context']]

+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -1161,6 +1161,12 @@ protected function rebuildContainer($environment = 'testing') {
+
+    // The request context is normally set by the router_listener from within
+    // its KernelEvents::REQUEST listener. In the simpletest parent site this
+    // event is not fired, therefore it is necessary to updated the request
+    // context manually here.

Is there a reason for this change? Does that mean that the router listener ensures that?

znerol’s picture

FileSize
1.66 KB
610 bytes

Is there a reason for this change?

Upon closer inspection the change to the url generator service definition does not seem to be strictly required as part of this patch. Let's try and revert that change.

Does that mean that the router listener ensures that?

Exactly. In 2.3 mode, the request stack is not injected into the router listener. The router listener therefore cannot possibly update the request context by itself. Whereas in 2.4 mode the router listener does maintain the request context from within a KernelEvents::REQUEST handler. (see RouterListener::onKernelRequest()). In the simpletest parent site we still need to update the request context manually. Before this was done upon synchronization of the request service - i.e. whenever something called \Drupal::service('request')->set(...).

znerol’s picture

znerol’s picture

Status: Reviewed & tested by the community » Needs review

Uh, no test results, let's trigger a test-run.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 20: 2223593-use-request-stack-in-router-20.diff, failed testing.

znerol’s picture

znerol’s picture

Status: Needs work » Reviewed & tested by the community

This looks like a testbot failure. Retest and back to RTBC.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 20: 2223593-use-request-stack-in-router-20.diff, failed testing.

znerol’s picture

Status: Needs work » Needs review
FileSize
1.68 KB

Reroll.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

re-rtbc

tim.plunkett’s picture

Component: base system » routing system

Haven't read the issue yet... Just putting it where people can find it.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 775184c and pushed to 8.x. Thanks!

  • Commit 775184c on 8.x by alexpott:
    Issue #2223593 by znerol: Decouple the router.request_context service...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.