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.

Issue fork redirect-2821158

Command icon 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

j_shb created an issue. See original summary.

berdir’s picture

Not 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

j_shb’s picture

Hm. 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?

berdir’s picture

I'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?

j_shb’s picture

I 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?

berdir’s picture

Sure, 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?

j_shb’s picture

Status: Active » Closed (works as designed)

Oh, 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.

berdir’s picture

Status: Closed (works as designed) » Active

Great.

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.

saradaprasad17’s picture

Assigned: Unassigned » saradaprasad17
Status: Active » Needs review
StatusFileSize
new1.5 KB

Hey, just checked that redirect is not working for node alias , so mentioned that in Help page and Readme.txt file .

purushotam.rai’s picture

purushotam.rai’s picture

I 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

purushotam.rai’s picture

Also, we have found out an alternative workaround on this: Using Redirect Domain Submodule

Thanks

berdir’s picture

Status: Needs review » Needs work

The 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.

purushotam.rai’s picture

Converting 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

oldspot’s picture

StatusFileSize
new779 bytes

I 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_query
where the source query is empty since no query parameters are specified at that point.

However, when the findMatchingRedirect function is called in the onKernelRequestCheckRedirect function in the file RedirectRequestSubscriber.php, the $request_query contains Drupal's 'hidden' q=source_path parameter 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.

oldspot’s picture

It 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

location / {
  # try_files $uri @rewrite; # Drupal <= 6
  try_files $uri /index.php?$query_string; # Drupal >= 7
}
</coded>

This means that the patch I submitted above is no longer required as the source query array no longer contains the rogue <code>q

parameter.

jmuzz’s picture

+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.

multiple path aliases would have same system path

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.

mfernea’s picture

My 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.

berdir’s picture

See also #2879648: Redirects from aliased paths aren't triggered as a related/duplicate issue which attempts to make aliased paths work.

herved’s picture

Hi 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 :)

berdir’s picture

Creating a merge request for a new idea that I mentioned in the linked issue.

Proof of concept for the UI, not functional yet:

acbramley’s picture

@Berdir I quite like this idea. Although it'd be nice to just be able to use aliases, this is a decent compromise.

mark_fullmer’s picture

Title: Document that URL redirects work from node/{nid} but not alias » Guide users who enter path aliases to use internal paths instead
Component: Documentation » Code
Category: Task » Feature request
Issue summary: View changes

Based 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.

mark_fullmer’s picture

mark_fullmer’s picture

Issue summary: View changes
mark_fullmer’s picture

Status: Needs work » Needs review

Creating a merge request for a new idea that I mentioned in the linked issue.

Proof of concept for the UI, not functional yet:

I'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.

herved’s picture

Coming 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.

herved’s picture

StatusFileSize
new7.37 KB

Snapshot of current MR for composer

herved’s picture

Ok my main question here relates to what should happen when we actually delete a node that has a redirect.

From #2879648-103:

For the node deletion problem:
- when a path alias is deleted,
- and a redirect for the source of the path alias exists
- if the existing redirect language matches the path alias language being deleted, we update the redirect source to the path alias url
- else if the existing redirect language == "und", we duplicate the redirect and set the redirect source and language according to the path alias being deleted.

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?

jwilson3’s picture

Huge +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?

mark_fullmer’s picture

Agreed 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.

leoenriquezp’s picture

I've re-rolled a patch that can be applied to version 1.12.0

herved’s picture

Status: Needs review » Needs work

I had a stab at this again but it still needs some work it seems.

herved changed the visibility of the branch 2821158-guide-users to hidden.

herved changed the visibility of the branch 8.x-1.x to hidden.

herved’s picture

FWIW 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_box ajax 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.

herved’s picture

Assigned: mark_fullmer » Unassigned
Status: Needs work » Needs review