The design of this module is such that redirecting from node/{nid} works even though redirecting from the associated alias does not. Per https://www.drupal.org/project/redirect/issues/2879648#comment-15899624 , the module maintainers have no plans to allow path aliases to redirect. Therefore, the next best thing would be to provide a validation layer that checks for entry of a path alias and informs the user that the internal path should be used instead.
Acceptance criteria
- [ ] When a content editor enters a redirect "from" path, new (AJAX) form validation checks if this is a Drupal URL alias.
- [ ] If it is a URL alias, the form provides two resolution options: use the system path, or delete the alias
- [ ] If the "system path" option is selected, the redirect should be saved as the alias source_path (i.e., internal URL)
- [ ] If the "delete alias" option is selected, the alias should be deleted and the user-supplied redirect be used as-is.
Example real-world usage
1. Content editor creates a "Publications" node (/node/123) with URL alias /publications
2. Subsequently, the organization decides this content should be hosted externally, e.g., https://academia.edu/org-name
3. Content editor goes to Redirect UI to redirect /publications to https://academia.edu/org-name. (The Redirect module does not support redirects from aliases -- hence this issue!)
3. When user enters /publications in the Redirect UI, they are prompted with a choice: should the redirect use the system path (/node/123), or should the alias /publications be deleted in concert with adding the redirect? This prevents a scenario where the site contains both a URL alias and a Redirect from that alias.
| Comment | File | Size | Author |
|---|
Issue fork redirect-2821158
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
berdirNot 100% sure what happens first. You could also try if #2704213: "Redirect from non-canonical URLs to the canonical URLs" not working with language code in url changes anything about it.
If de-alias really happens first, then we could de-alias when creating the redirect maybe
Comment #3
j_shb commentedHm. Would it be better to de-alias during redirect creation, or instead look for both canonical and non-canonical URL's when detecting a redirect?
Comment #4
berdirI'm not sure.
The thing is, I don't understand why you would even have both an alias and a redirect for the same path? Aliases are for existing things, redirects are to go from a not-actually existing thing to an existing thing. Why would you have an alias for something that doesn't exist?
So maybe instead of trying to do something automatically, we should actually validate and prevent such redirects, possibly with an easy way to drop the alias?
Comment #5
j_shb commentedI think you're making a jump to say "redirects are to go from a not-actually existing thing." That's one use for sure, but not the only one.
One use case (which I hinted at in my original comment): Create/edit a node that is available in views or via node reference but redirects from it's canonical URL.
I feel like the D7 version of this module de-aliased during redirect creation (?). Want me to take a stab at a patch?
Comment #6
berdirSure, feel free to do that.
Fair enough, https://www.drupal.org/project/rabbit_hole might be a better way to solve that use case, though?
Comment #7
j_shb commentedOh, hey! That's a cool module. Didn't even know it existed.
My original hope was to at least document for posterity the way the module worked. I'll use Rabbit Hole and/or canonical redirects moving forward.
Thanks.
Comment #8
berdirGreat.
Lets keep this open, though. I just closed a duplicate of this and there might be conflicts with left-over aliases, so it seems like a good thing to de-alias or warn or something.
Comment #9
saradaprasad17 commentedHey, just checked that redirect is not working for node alias , so mentioned that in Help page and Readme.txt file .
Comment #10
purushotam.rai commentedComment #11
purushotam.rai commentedI just tried to get into details how the redirect process works and found that fetching of rid (request object) is based on generation of hash. Now, this generation of hash while saving redirects from form is based on the input URL, so let's say we have 2 nodes and they have following path alias:
node/1 -> /abc
node/2 -> /def
Now, if we try to redirect from /abc to /def then while saving redirect hash is generated making use of /abc.
Now when we hit /abc, expected behavior is to redirect to /def but the route subscriber of Redirect module when tries to find any corresponding redirect rid, it is not able to find any. This is because Route Subscriber uses processInbound function of PathProcessManager service to do inbound processing which changes path to internal path and hence the hash generated for matching in db is different than the one stored there.
Proposed Solution:
As of now, IMO Route Subscriber should not convert request URL to internal path for hash generation. So, what we can do is instead of using core PathProcessManager service we should create our own service extending the core one and override processInbound to exclude alias manager's inbounding so that URL is not converted to internal system path. This way we will end up with perfect match.
Need views on this.
Thanks
Comment #12
purushotam.rai commentedAlso, we have found out an alternative workaround on this: Using Redirect Domain Submodule
Thanks
Comment #13
berdirThe submodule doesn't really scale to a large number of redirects, though.
I don't think what you describe is necessary. All we IMHO need to do is do the same path processing when actually saving an alias so that we convert the alias to the system path.
Comment #14
purushotam.rai commentedConverting the alias to system path and then generating the hash from that has the tendency to create ambiguity as we can have scenarios where multiple path aliases would have same system path and in that case the hash generated would be same for all such cases which are definitely not good from the current module architecture point of view.
Thanks
Comment #15
oldspot commentedI just stumbled upon a similar problem as described in #11 in my project - if I have a redirect automatically generated during a node edit where the node's url alias changes, or if I manually input a 'source' path and try to redirect it to another path, then none of these redirects work and they simply return a 404 page not found.
After some debugging I found that when the redirect source gets saved in the table the has created is:
source_path + language + source_querywhere the source query is empty since no query parameters are specified at that point.
However, when the
findMatchingRedirectfunction is called in theonKernelRequestCheckRedirectfunction in the fileRedirectRequestSubscriber.php, the$request_querycontains Drupal's 'hidden'q=source_pathparameter which causes the hash to not match the one saved in the database when the redirect was created initially.I have created a simple patch for this by removing the 'q' parameter from the $request_query array, while leaving any other paramaters that might exist intact.
This has solved my problem and aliases and manually added redirects work perfectly fine.
Comment #16
oldspot commentedIt turns out for me it was an issue with the nginx configuration not getting rid of the ?q parameter correctly.
After reading more into the common drupal configuration for nginx (https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/) I changed my main location to the following
parameter.
Comment #17
jmuzz commented+1 for this issue. It seems silly to pop up a message saying "it's recommended to use a URL alias instead" when that doesn't cover the typical use case of wanting the browser's URL to change... And also fail to mention in that pop up message that what you're trying to do isn't just "not recommended" but it's not even going to work at all. Since using the alias here will result in nothing happening I don't see what the harm could be in having it convert that into a node/xyz URL automatically since that will make it work.
I can't imagine this use case at all. So you have multiple aliases going to the same system path... But you want them each to redirect to different places? In that case it seems like you don't want those aliases and should delete them so you can add the redirects you want.
My use case is like, my customer wants to be able to add redirects from certain pages in the IA that they don't have content for yet to one of their child pages. Later they would like to add content to the higher level page and remove the redirect... So in that case they would like the one single alias for the page to remain in place for when they remove the redirect.
Who is the person who wants multiple aliases to the same path and have them redirect differently and why do they want that?
I may end up using rabbit hole instead... I just hope nobody ends up wanting redirects from non-node pages too... It's too bad this module doesn't seem to be lined up to be such a general solution.
Comment #18
mfernea commentedMy use case is: I have an unpublished node. If a visitor loads the page he gets a 403. So, I want to add a redirect for it. Of course, for ease of use, I would like to add the alias, but it doesn't work. I also agree that at least an alert message should be added.
Comment #19
berdirSee also #2879648: Redirects from aliased paths aren't triggered as a related/duplicate issue which attempts to make aliased paths work.
Comment #20
herved commentedHi everyone, I just posted a rewrite of the patch in #2879648: Redirects from aliased paths aren't triggered.
Feedback there are most welcome and appreciated.
Cheers :)
Comment #22
berdirCreating a merge request for a new idea that I mentioned in the linked issue.
Proof of concept for the UI, not functional yet:
Comment #23
acbramley commented@Berdir I quite like this idea. Although it'd be nice to just be able to use aliases, this is a decent compromise.
Comment #24
mark_fullmerBased on the direction this is going in #22 and later, I think we can rename this issue to "Guide users who enter path aliases to use internal paths instead." I will also update the issue description to capture this.
Comment #25
mark_fullmerComment #26
mark_fullmerComment #27
mark_fullmerI've added the business logic for the functional bits. The test failure in the MR appears to be unrelated (it's also failing on 8.x-1.x)
This is ready for functional/code review.
Comment #28
herved commentedComing from #2879648: Redirects from aliased paths aren't triggered
I did some thinking back then on that issue (see comment #103 / #108) and I ended up with a similar conclusion to @berdir, which is that we should only inform/guide the user when they input aliases.
Till now I was using the patch from #104, but the approach here seems like an it improves on it. So thank you for moving it forward.
Comment #29
herved commentedSnapshot of current MR for composer
Comment #30
herved commentedOk my main question here relates to what should happen when we actually delete a node that has a redirect.
From #2879648-103:
Say we have an EN /node/123 with alias /foo
And a user created a redirect from /node/123 to /bar. At this point both /node/123 and /foo redirect to /bar.
Shouldn't we do anything when the node (and so path alias) gets deleted? so we maintain the canonical /foo > /bar redirection?
Comment #31
jwilson3Huge +1 to comment #30, but doesn't that problem already exist today with or without the implementation here? For that reason, this should be split off to a follow-up, for its own discussion and implementation, independent of the scope of this issue. It's unclear whether that should then also be marked postponed on this issue or not. To the folks working on the MR, is there something the code is introducing here that would facilitate a fix for this?
Comment #32
mark_fullmerAgreed with #30 that what to do with deleted nodes should probably be kept out of scope, as this proposed change does not introduce that problem.
Comment #33
leoenriquezp commentedI've re-rolled a patch that can be applied to version
1.12.0Comment #34
herved commentedI had a stab at this again but it still needs some work it seems.
Comment #38
herved commentedFWIW I'm still running a custom re-rolled patch from #2879648 (comment 104) but would like to consolidate here.
MR !45 was built on the widget's
status_boxajax callback. #3057250: Validation issue on adding url redirect removed that callback in 1.13, so there was nothing left to rebase onto.I created a new MR that reimplements the feature in
RedirectForm::validateForm()instead. !45 can be closed in favor of it.What it does
When the source of a new redirect is a URL alias, the form replaces it with the system path behind that alias, and asks for one more save to confirm.
Aliases are looked up in the language the redirect is for (not the language of the person creating it).
No "delete the alias" option
The summary asks for two options: use the system path, or delete the alias.
I left out the second one. On a site with pathauto, the alias comes back the next time the node is saved.
redirect_path_alias_insert()then deletes the redirect, so the option undoes itself.The summary offers this choice to avoid a site with both an alias and a redirect from that alias. Replacing the source already avoids that, because no redirect from an alias is ever saved.
It would also introduce quite a lot of complexity (more logic, need to check permission to delete URL aliases, etc).
To redirect one URL only and keep the page reachable, set the redirect language to the language of the alias.
Out of scope
As mentioned in #30, a node alias can be deleted later and canonical redirection should be preserved ideally.
I will create a separate issue on that, as agreed in #31 and #32.
Comment #39
herved commentedI opened #3620828: Fix phpstan / phpcs jobs in pipeline on Drupal core 11.4 for the failing CI