Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
- In Drupal, we have a concept of "administrative route", expressed via the
_admin_route
route option. - Certain things happen for administrative routes, such as
AdminPathConfigEntityConverter
andLanguageNegotiationUserAdmin
. - Caching is also affected, though see #2877528: Change Dynamic Page Cache's response policy from "deny admin routes" to "deny html admin routes" about possibly changing that.
AdminRouteSubscriber
automatically marks routes with a path that starts with/admin
as administrative.- As a result, some REST module routes get marked as administrative, such as GET requests to
MenuLinkContent
andShortcut
entities, though it's not at all clear why we'd want any of the administrative route behaviors happening for those requests. - Outside of core's REST module, who knows what use cases contrib has for non-HTML routes and whether it's clear what "administrative"
means for those use cases.
Proposed resolution
Option 1: Keep core's current behavior of marking/admin/*
routes as administrative, regardless of format. If it's undesirable for the canonical URL of an entity to be administrative, then move that URL out of/admin
. See,
for example, #2873529: BlockContent, MenuLinkContent, and Shortcut define incorrect canonical links.- Option 2: Change
AdminRouteSubscriber
to only mark/admin/*
routes as administrative if they're HTML routes. For non-HTML routes, require explicit opt-in to_admin_route
, not magic based on URL path. This would be a potential BC break for contrib that was relying on the existing magic. Option 3: Change REST module to mark all its routes as non-administrative by default. That's implemented in the patch in comment #2.Option 4: Change REST module to only mark entity resources as non-administrative. This could be accomplished viaEntityResource::getBaseRoute()
.Option 5: Change REST module to only mark GET requests of entity resources as non-administrative. This could be accomplished viaEntityResource::getBaseRoute()
and its$method
parameter.
Remaining tasks
Decide on which option makes the most sense.Option 2 was chosen, per routing system maintainer @tim.plunkett in #9.Implement that option and create a change record to communicate the corresponding BC break.
User interface changes
None.
API changes
Routes that don't serve HTML, but for example JSON, and have a path that starts with /admin
are no longer automatically marked as admin routes.
Data model changes
None.
Comment | File | Size | Author |
---|---|---|---|
#18 | 2874938-16.patch | 9.83 KB | Wim Leers |
#18 | 2874938-16-test-only.patch | 8.08 KB | Wim Leers |
Comments
Comment #2
Wim LeersSo we do mind limiting
AdminRouteSubscriber
to HTML routes, but we don't mind making the REST module's routing aware of concepts only relevant to HTML? This makes little sense to me.Anyway, here's a patch.
Comment #3
effulgentsia CreditAttribution: effulgentsia at Acquia commentedIs "administrative route" a concept that is only relevant to HTML? That's the question. I rewrote the issue summary, and am setting this issue to Active in order to have a discussion on which direction to take.
Comment #4
Wim LeersI think "administrative route" is only relevant to HTML, yes.
The whole reason it's called "administrative" in the first place is because of the "admin" or "back end" of a site, which uses the "admin theme".
That is the entire purpose/goal/semantic/origin of
_admin_route
: to determine which HTML pages should use the admin theme. That is: all HTML pages that have a URL starting with the/admin
prefix, as well as the few exceptions that don't have that path prefix, but want to use the admin theme anyway, depending on configuration: the/node/add/*
HTML pages._admin_route
is the abstraction for that: so that that is the sole factor in determining whether a route should use the admin theme during theme negotiation (see\Drupal\user\Theme\AdminNegotiator
). Then the/node/add/*
routes can just set that_admin_route
route option, and other exceptional cases are then also possible.IOW: if we didn't have
_admin_route
, then we'd be forced to stick to just/admin
path prefixes or also hardcode whatever crazy logic to deal with the exceptions.Comment #5
Wim LeersNote that this soft-blocks #2765959-188: Make 4xx REST responses cacheable by (Dynamic) Page Cache + comprehensive cacheability test coverage.
Comment #6
Wim LeersComment #8
Wim LeersCome to think of it, this is actually more of a
routing system
issue probably! At the very least, it's a question where we'd want a routing system maintainer to weigh in.Comment #9
tim.plunkettCore has only had two reasons to care about whether a path is "admin" or not:
I honestly don't know if the langcode portion affects non-HTML routes.
Upon first reading, I like option #2.
However, how will you know if the route explicitly opted in or not? The check for
/admin/
actually goes and sets the route option...Comment #10
Wim LeersThanks, Tim!
I also like option 2. Patch attached that implements it.
For option 2, the IS says that non-HTML routes would have to explicitly opt in. Since
\Drupal\system\EventSubscriber\AdminRouteSubscriber
sets the_admin_route
route option only for HTML routes, that means that non-HTML routes would have to set that route option themselves in their route definition. So it's a non-issue. Unless I'm misunderstanding you.Comment #12
tim.plunkettYou misunderstood me, but my point also didn't make any sense in light of that patch. I originally envisioned Yet Another Subscriber having trouble introspecting this, but of course it can live inside the existing subscriber.
Comment #13
Wim LeersOkay!
So what do you think about #10? :)
Comment #14
tim.plunkettYes, but with one small change. Formats are specified as pipe-delimited, so this needs some extra finesse.
Added a unit test, of which the last case covers my change.
Comment #16
Wim LeersD'oh, of course! Thanks for the fix, and the test! ❤️👌
The failures aren't in your new test, but in the existing REST test coverage, which is now failing only because the work-around is no longer relevant :) I can simply resolve the two @todos, and tests then pass! (#2765959: Make 4xx REST responses cacheable by (Dynamic) Page Cache + comprehensive cacheability test coverage would have to add even more of those work-arounds until this is fixed.)
Comment #17
borisson_I think we should retitle this issue - it's been decided that only those non-html routes that also have a html as alllowed format should be marked as administrative.
The code looks solid as do the tests, should we also upload a test-only patch?
Comment #18
Wim Leers#17++
Done!
Comment #19
Wim LeersComment #21
borisson_Awesome, thanks!
Comment #22
xjmI was going to ask for a routing subsystem maintainer review -- turns out that's @tim.plunkett and he's agreed on the solution above.
Probably we should add a change record? Thanks!
Comment #23
Wim LeersCR created: https://www.drupal.org/node/2921521
Comment #24
xjmCommitted to 8.5.x and published the change record. Thanks!
Comment #25
Wim LeersThis allowed me to close #2877528: Change Dynamic Page Cache's response policy from "deny admin routes" to "deny html admin routes" since it's now obsolete. And it allowed me to rebase #2765959's patch, the new one is 5 KB smaller because it doesn't need to handle the edge cases that HEAD (before this patch went in) was causing for lots of scenarios: #2765959-231: Make 4xx REST responses cacheable by (Dynamic) Page Cache + comprehensive cacheability test coverage — yay!
Comment #26
Wim Leers