Problem/Motivation
When the language switcher block is rendered for 404 pages an interesting thing happens. Without big_pipe enabled we get links to system/404 - so we get links to pages which are a 200 response but with 404 content. With big_pipe enabled and a logged-in user we get links to the front page. This is because only the sub-request has the correct routing information.
Steps to reproduce
Once #3348592: [regression] Language switcher block throws exception when no route is matched run \Drupal\Tests\language\Functional\LanguageSwitchingTest::testLanguageBlock()
Proposed resolution
Not sure. But the fact that system/401, system/403, system/404 and system/4xx are all valid URLs on a Drupal site is very odd. If you hit them directly they all return a 200 response.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|
Issue fork drupal-3349201
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
catchI tried to fix big_pipe via #3348592-22: [regression] Language switcher block throws exception when no route is matched and failed, but it illustrates the problem:
The 404 and 403 patches are subrequests to a route, that we allow to be configured by path in the admin UI. This was done to mirror Drupal 7's settings which also allowed a URL (but directly executed the controller without a subrequest or anything like that iirc).
This affects big_pipe, because placeholders are executed outside the subrequest context, so they don't know have the context of the 404 or 403 page.
The patch I wrote forces the main request to have the routing information for the 404 or 403 page, but this pollutes links with system/404 and similar, which we don't want.
A possible alternative would be to directly execute the controller (i.e. revert even closer to what Drupal 7 does) without any subrequest at all.
If that doesn't work, another possibility might be to allow admins to specify an entity, and modules to override the behaviour programmatically.
Comment #3
catchHere's a variation of #22 which only swaps the routing information for the main request if it doesn't already have some.
For me this fixes
Drupal\Tests\system\Functional\System\AccessDeniedTestComment #6
alexpottThis appears to be caused by #2613044: Requests are pushed onto the request stack twice, popped once and fixing that fixes this!
Comment #7
catchPostponing on #2613044: Requests are pushed onto the request stack twice, popped once
Comment #9
nicxvan commented#2613044: Requests are pushed onto the request stack twice, popped once is in, can this be closed now?
Comment #10
alexpottSo this has been fixed - but I think this was fixed by a different issue.
Note we still have problems with big_pipe and routing - see #3565887: Null is used as an offset in task and action managers of the menu system. For me it feels as though big pipe should have special request handing for 4xx requests and somehow that big pipe request should have the same request context as the sub request.
Comment #11
alexpottYeah this was fixed by #3554414: Use #placeholder_strategy_denylist for CacheOptionalInterface blocks to prevent them being rendered by BigPipe which means that big_pipe is not rendering the language switcher block.
Comment #12
alexpottAnd yeah if I remove the fix from that issue and allow the switcher block to be placeholdered by big_pipe everything is still broken - so #6 was wrong.
Comment #13
smustgrave commentedFree to mark it as a duplicate or outdated?
Comment #15
alexpottComment #16
catchPreventing big pipe from placeholdering in subrequests makes a lot of sense to me. It would good to separately look at reducing our reliance on subrequests for error handling since that causes us a lot of other (usually more serious) problems.
Comment #17
andypostis this changes in test is enough for coverage?
Comment #18
alexpott@andypost well I think so - this disabling bigpipe is well tested and this does just that.
Comment #19
berdirI think this makes sense. I was wondering why this isn't using the more explicit isMainRequest(), but I understand that this is only available
on the relevant events, not the request object.
There is a warning on getParentRequest():
I think that isn't a concern here, we aren't really doing anything with the parent request, just check if there is one, and I don't think we support ESI or other main/sub request features that would be relevant here. If anything, the same logic likely applies in such cases too.
While #2613044: Requests are pushed onto the request stack twice, popped once has not fixed this, my understanding is that it made this fix possible, because before that, there would always have been a parent request. That means even though this is a bugfix, we can't backport it to 11.3 as that I think would completely disable bigpipe.
Comment #20
alexpott@berdir you are completely correct that #2613044: Requests are pushed onto the request stack twice, popped once enables this fix :) I should have pointed that out.
Comment #24
catchCommitted/pushed to main and 11.x, thanks!
Not the most serious of actual bugs, but annoying and disconcerting.
Comment #27
solideogloria commentedI see this was fixed in main and 11.x, but I don't see the fix in 11.3.9, despite there being a release newer than the commit date. Why is that?
Comment #28
nicxvan commented11.x is 11.4 at this point which hasn't come out yet.
This wasn't backported to 11.3.x so wouldn't be in that release.
Comment #29
solideogloria commentedOkay, thanks. I can wait.