Problem/Motivation
I'm not sure if this is a Views bug or a core bug.
How to reproduce
1. Create a Drupal 8.5.0 site.
2. Create a view and set the path to user/% to override the user profiles.
3. /user/login and /user/logout and /user/register will now show the 404 page. Using Drush to log in and removing or changing the path of the view set to "user/%" will allow login and logout to work normally.
I have always used "user/%" in a view to override the user profile display, but since 8.5 it does not work.
(Edit: Based on the discussion, I edited the summary to reflect that the bug affects 8.5.x, not just 8.5.1.)
Reference info
Additional details can be found in this forum support thread and on Drupal Answers.
Proposed resolution
Fix the router to re-order the route by fitness once route filtering is complete. Since filtering removes and re-adds routes it is not possible to maintain fitness whilst filtering.
Remaining tasks
User interface changes
None
API changes
None. One new protected method added Router::applyFitOrder().
Data model changes
None
| Comment | File | Size | Author |
|---|---|---|---|
| #44 | 2959370-44.patch | 9.66 KB | alexpott |
| #44 | 41-44-interdiff.txt | 534 bytes | alexpott |
| #41 | 2959370-41.patch | 9.66 KB | dawehner |
| #41 | 2959370-test.patch | 2.23 KB | dawehner |
| #35 | interdiff-2959370.txt | 3.67 KB | dawehner |
Comments
Comment #2
andrewkillen commentedit is also /user/register that is affected.
Comment #3
lendudeWhen I rollback to 8.5.0 and follow the steps in the IS I also get the 404, no need to go to 8.5.1 to make it break. So not sure if this is 8.5.1 related really.
Comment #4
christianadamski commentedWe just ran into this problem, though I only found this issue by chance. By some drush magic I was able to fix it fairly quickly once identified.
Nevertheless: Setting a view to path "user/%" is something recommended and described in a lot of "HowTos" around the web, plus some modules do this by themself. Once this has happened, anyone but a very capable user with Shell Access is unable to access his site and fix the issue.
So I think the "Critical Issue" criteria "Render a site unusable and have no workaround." is fulfilled here.
Comment #5
swentel commentedI'd would say that it's normal it would break those pages, but not necessarily return a 404.
Also, user/%user is probably much safer to use so that user/logout (or anything on user/%) is not affected.
Comment #6
giorgoskIt seems indeed critical as
user/%path overriding with views used to work for Drupal 8 up to now@Swentel I tried changing the view to use
user/%userand the login/logout worked again but the view stopped working as it shouldSo currently there is no workaround other than changing the view path
Comment #7
giorgoskThe easiest solution/workaround that I found was to alter the paths login / logout / register / password
here is small module that does this https://github.com/GiorgosK/user_routes_alter
Comment #8
lendudeHere is a fairly ugly test, but this illustrates the point....
@swentel I'm also not surprised they would break, I'm surprised it took till 8.5.x to break...but a regression it is....
Comment #10
lendude@mixologic queued the patch for 8.4.x.
The passing 8.5.x php 7.0 result is actually against 8.4.x, the php 7.1 result is against 8.5.x
Comment #11
mxh commentedI think the source of this problem is that the way of route matching process is now "correct" since core 8.5. It includes some route filters, and one of them is
Drupal\Core\Routing\RequestFormatRouteFilterwhich changes the ordering of matched routes by checking for the parameter_format, default set to valuehtml.Guess the related change record is this one #2883680: Force all route filters and route enhancers to be non-lazy
The Views module does set the
_formatparameter tohtml, while other core components do not (for example all entity routes). Here is the location where Views does this: ClassDrupal\views\Plugin\views\display\Pageline 93-94:This results in the situation that routes generated by Views would mostly win on the route matching process.
Maybe the other route definitions need an explicit parameter definition of
_formattoo, or the logic of the route filterDrupal\Core\Routing\RequestFormatRouteFiltermust be changed.Comment #12
berdirMaybe #2854543: NegotiationMiddleware calls $request->setRequestFormat('html') when there is no _format request parameter, but shouldn't helps with this too, then?
Comment #13
it-cru@Berdir : I've tried last applying patch from your linked issue #2854543-72: NegotiationMiddleware calls $request->setRequestFormat('html') when there is no _format request parameter, but shouldn't, but user/login & logout also does not work with an active view with user/% path.
Comment #14
ptmkenny commentedComment #15
ptmkenny commentedComment #16
landsman commentedI have same problem, on my Thunder based website.
After I disabled my custom view with path "/user/%" problem was gone.
That view was provided by old Thunder distro (infinite_user).
Comment #17
dawehner#2969297: It is not longer possible to override /taxonomy/{}/view with a more specific path without brekaing /taxonomy/{}/edit contains some more technical analysis why this happens.
Comment #18
mxh commentedSo is this issue now the main one to address the problem?
Relating #2449143: REST views specify HTML as a possible request format, so if there is a "regular" HTML view on the same path, it will serve JSON as "the root of this problem".
Comment #19
dawehnerI guess :) #2449143: REST views specify HTML as a possible request format, so if there is a "regular" HTML view on the same path, it will serve JSON caused not just one problem.
Here is a proposal: Let's re-enforce the route fit with another route filter.
I manually tested the
/taxonomy/{}/editexample, and it works for me as expected.Comment #21
dawehnerTurns out I was using probably php 5.6 syntax.
Comment #22
mxh commented#21 looks reasonable to me (although I wouldn't agree the already high complexity and bloat of the existing route matching process).
Comment #23
lendudeCombined the fix with the test from #8 and minor cleanup.
The fix looks reasonable, but my knowledge of the routing system isn't up to speed enough to judge if this is the best way to do this.
Comment #25
alexpottDiscussed with @dawehner. We weren't sure whether this should be a filter or just part of the router that happens after the routes are filtered. I'm leaning towards it not being a filter because I don't think a site should be able to opt out of this behaviour.
Comment #26
alexpottDiscussed a bit more with @dawehner. I think we might need to sub class RouteCollection so that our one is fit aware. This is because with the current solution the filters become unaware of the route that is going to "win". Because the order at the end of filtering might be changed. This fit-aware route collection would always add into the right spot so we no longer need to resort at the end of the chain.
Comment #27
dawehnerI'm not sure the route collection solution will really work as good as expected, because there is a lot of code out there which does:
new RouteCollection().Subclassing the class by ourself though will not just work.
Here is a patch which moves the fit ordering to the router itself.
Comment #28
catchIf it's re-applying instead of just applying, I think we need an explanatory comment.
Comment #29
dawehnerI do agree. I tried to massively improve the documentation.
Comment #30
dawehnerThis is a generic routing problem.
Comment #31
alexpottI think this is a good fix for now. We have explored trying to fix this in a way that doesn't require a resorting at the end but that doesn't look like it is going to be simple so this is probably the best we can do.
I think we missing some unit testing of the new method since atm the only test added is a views test.
I think we can make this comment slightly clearer.
How about...
Comment #32
ashutosh.mishra commentedI have facing same problem so that I have used alterRoute of login and logout pages
changed PATH :
/user/login > /login
/user/password > /password
/user/logout > /logout
/user/register > /register
Please find the process for Altering existing routes and adding new routes based on dynamic ones at this page https://www.drupal.org/docs/8/api/routing-system/altering-existing-routes-and-adding-new-routes-based-on-dynamic-ones
Comment #33
hctomThe patch from #17 fixes the problem on our side as well for views routes like
/blog/2018(while the2018part is a contextual filter with validation to be numerical) that broke our feed URL at/blog/feed(wherefeedis no contextual filter and thus the full/blog/feedroute should take priority over the one with the dynamic year argument).Thanx for fixing this!
Comment #35
dawehnerI used
git diff --color-wordsto look at the suggestions from @alexpott.On top of that I added a unit test for this specific class.
Comment #37
tormiRemoved version number from title.
Comment #38
alexpottNeeds an @group annotation.
The blank line here contains spaces.
Comment #39
alexpottAlso as far as I can see the test does not fail if the patch is not applied to the Router so it's not quite covering what we hope it is.
Comment #40
dawehnerComment #41
dawehner@alexpott and @dawehner worked on this patch together as part of the DrupalNorth Unconference.
Comment #44
alexpottFix a minor whitespace issue.
The new unit test now fails without the fix. Nice.
Comment #45
swentel commented+1 one commit, been bitten this by this after an upgrade, patch works fine!
Comment #46
catchCommitted and pushed 18ff78aaf0 to 8.7.x and 9c94695902 to 8.6.x. Thanks!