Updated: Comment #147
Problem/Motivation
Suggested commit message:
git commit -m 'Issue #1796596 by stefan.r, Eric_A, Steven Jones, Dave Reid, damien_vancouver, azinck, DamienMcKenna, heddn: Fix and prevent circular redirects' --author="stefan.r <stefan.r@551886.no-reply.drupal.org>"
Enabling pathauto and redirect module and setting redirect to " Automatically create redirects when URL aliases are changed." (default behaviour), change a node's url from (original) to (something else). Then, change the node's url back to (original). Result: Infinite loop warning appears on node access.
Proposed resolution
Initially an approach of deleting old aliases if a new alias about to be saved matches it was taken. After reviewing the patch in #146, the module maintainer (Dave Reid) advised against this. Comments #193, #195, #199, #204, #286 provide further background on the reasoning disabling a redirect was chosen instead. An example use case includes: "All it takes is a content editor unwittingly setting an alias that collides with some important redirects and the redirects are silently killed, never to be seen again."
The patch in #249 is the latest attempt at implementing this and was marked RTBC as of #266. It includes the following functionality:
- On path update disables old alias if new alias about to be saved matches it.
- Prevents any circular redirect from occurring by checking for it in
redirect_redirect()
. - Comes with tests to verify circular redirects are prevented.
- Includes a hook_update_N() to disable any existing redirects.
A new iteration of this patch has been posted in #422, which also addresses the feedback from Dave Reid.
Remaining tasks
None, all of Dave Reid's most recent feedback have been addressed in the most recent patch.
User interface changes
Disabled/enabled status shown on node edit screen and on redirect overview and edit screens.
API changes
Two new hooks are introduced so other modules can react to redirects being enabled/disabled.
Original report by nightskyone
Recent updates to sites Pathauto module and Redirect Module causes an Infinite loops
Comment | File | Size | Author |
---|---|---|---|
#516 | interdiff-512-516.txt | 564 bytes | stefan.r |
#516 | 1796596-516.patch | 23.35 KB | stefan.r |
#513 | interdiff-489-512.txt | 5.9 KB | stefan.r |
#512 | interdiff-504-512.txt | 1.61 KB | stefan.r |
#512 | 1796596-512.patch | 23.35 KB | stefan.r |
Comments
Comment #1
pjcdawkins CreditAttribution: pjcdawkins commentedThis is a Redirect module issue, and it's a duplicate of #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions.
Comment #2
Dave ReidNo, this is a separate issue. Debating removing the manual flood detection for redirect loops is different from "let's prevent circular redirects from happening in the first place".
Relevant comments from #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions
Comment #3
Eric_A CreditAttribution: Eric_A commentedNothing wrong with a last line of defense.
Something like this.
Comment #4
Eric_A CreditAttribution: Eric_A commentedI just realized that the posted patch (#3) is missing URL language. I suppose there may be redirect cases where the target URL language is different from the default? Leaving at "Needs review" for now.
Also, I'd like to make a case for considering this a bug rather than a feature request. There's so much going on with pathauto, i18n and the like. Redirect should ultimately prevent circular redirects, no?
Comment #5
hass CreditAttribution: hass commentedCannot review and test now, but looks ok. In general I'm still asking me why we allow redirects to be saved if this will cause endless loops. Marking them as warning or error sounds plain wrong to me.
Comment #6
Eric_A CreditAttribution: Eric_A commentedThis one uses current_path() and adds the URL options.
Comment #7
Eric_A CreditAttribution: Eric_A commentedHmm, wait, current_path() can't be right here...
Comment #8
Eric_A CreditAttribution: Eric_A commentedThis one handles query parameters and absolute URL's.
Comment #9
lsolesen CreditAttribution: lsolesen commentedApplying this patch solves the problem for me. I agree with @hass, those redirects should never be saved, if causing endless loops. For me however, it was caused by the upgrade to rc1. There was no redirect loop prior to that for me.
Comment #10
fenstratSame situation as @lsolesen. I'd say this is RTBC.
Comment #11
hass CreditAttribution: hass commentedI do not think that last patch is correct. If my current path is
foo
and my node has alsofoo
, I can add as many query params as I'd like and the loaded node is still the same. In such a case a url likefoo?foo=bar
will also trigger an endless loop. I have not tested it, but I think we need to ignore all URL query params.Comment #12
fenstrat@hass makes a good point, so that'd be similar to #6.
Comment #13
Eric_A CreditAttribution: Eric_A commentedA redirect from foo?foo=bar to foo?whatever=somevalue is legit. And by itself this implies just one redirect, no looping. You'd only get in trouble when there's a second redirect in the system from foo?whatever=somevalue to foo?foo=bar, but that type of loop is not in the scope for the patch in #8. It does target redirects like foo?foo=bar to foo?foo=bar and foo/bar to foo/bar.
Comment #14
damien_vancouver CreditAttribution: damien_vancouver commentedWhile the patch from #8 did prevent the error from occurring for me, we should really be fixing the problem, instead of detecting and working around it. If we did commit #8,it should be in addition to actually fixing the problem and old data.
I am able to cause new instances of the Oops, looks like this request tried to create an infinite loop. We do not allow such things here. We are a professional website! message by editing a node and setting its URL Path to be the same as an existing redirect to that same node.
It's possible to fix the old data using the query from #19 in #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions.
To prevent it happening in future, redirect module must prevent nodes from being saved with an URL path that matches an existing redirect to that node.
I describe the cause of the problem, the fix, and prevention in more detail below:
Cause of the problem
Adding a redirect works properly. If you try and add a redirect to an existing URL alias, the redirect module correctly prevents you, with the message: "You are attempting to redirect the page to itself. This will result in an infinite loop."
However nothing prevents you from editing a node and setting its URL alias to be the same as an existing redirect. Since rc1 of redirect this causes the Oops error message when you go to one of the duplicate URLs.
Steps to reproduce
The following steps will reproduce the problem:
Prevention
This could be prevented by having redirect implementing hook_node_validate(). Or adding a validator function to certain node edit forms via hook_form_alter(). Or quietly deleting the duplicate redirect row at node save time. I'm sure there are a number of other ways as well... Which would be best?
The Fix (for existing bad data and the Oops message)
For fixing existing bad redirects, the query in #19 from #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions works great.
Show records to be deleted:
Delete redirects shown in above query:
I think this query belongs in a redirect module DB update rolled out the same time as the fix the problem above. This will fix bad data and prevent the problem from happening in the future.
If we do that, we shouldn't need the patch in #9... but it might be nice to have anyway for situations where people get corrupt data somehow (via a buggy contrib module, failure to run the DB update, or who knows what else).
Thoughts? I could make a patch for this plan, if we can agree on which method is best.
Comment #15
Eric_A CreditAttribution: Eric_A commentedEDIT: changed "active alias" to "primary alias".
@damien_vancouver, the clean-up query needs work. Would you be willing to open a separate issue? I'd be happy to help on getting that one done. There are at least two things to deal with when running such a database query:
1) Language.
2) The other is the fact that there may be multiple aliases in the database for one system path. The primary one is the one to check against, but it might be the case that (at times) Redirect selects a different one as the primary one than Drupal Core does.
I think it would be wise to keep this issue focused on just one problem space: the last line of defense for one looping case: redirect to self.
Comment #16
damien_vancouver CreditAttribution: damien_vancouver commented@Eric_A : I have opened a separate issue: #1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect. Please have a look at comment #1, where I carry on the discussion from #14 and #15 here.
Can you please update the description and/or title of this issue so it better describes the last line of defense thing? Dave Reid described it in #2 as "let's prevent circular redirects from happening in the first place" but really it's now become "let's detect circular redirects are in the process of happening and stop after the first redirect".
Lastly, a +1 from me for the patch in #8, now that I understand that duplicate url_alias entries are allowed for a single source path. That might be bad data a user can't edit their way out of, so having a last line of defence like #8 would be the only way to stop the redirect from happening.
Comment #17
damien_vancouver CreditAttribution: damien_vancouver commentedI was looking into test coverage of this problem and I found that the Redirect functional test is actually failing because of this issue, but the test isn't currently detecting the failure.
With 7.0-1.0-rc1, the testPathChangeRedirects() function creates a node with alias "first-alias", then resaves it as "second-alias", then again as "first-alias" (which fails) and finally back to "second-alias" (which also fails).
The failure happens in one of two ways, which appears to be a timing thing. I consistently get one of each kind of these failures when running the Redirect functional tests:
This second one looks like this in the debugger - it appears that Simpletest just ends the request after 6 redirects in a row, and then since there are no assertions running it doesn't see that there was a problem:
Adding two asserts to the second and third drupalPost in testPathChangeRedirects() catches this problem and fails the test without the fix from #8 applied. The saves are successful only if there is an HTTP 200 in the headers, and no Oops error message appears in the page text.
I've attached a patch of the test only with it failing, and a re-rolled #8 with the test in there which passes.
I agree with Eric's comments in #13 with regard to the foo?foo=bar paths. Should the issue status be set back to Needs Review?
Comment #18
damien_vancouver CreditAttribution: damien_vancouver commentedSetting issue status to Needs Review and re-attaching those patches so the Testbot sees them.
Comment #19
ewenss CreditAttribution: ewenss commentedCan we please make this module UNAVAILABLE or CARRY A BIG WARNING IN RED at its download page?
Since my infinite loop occurred at my home page (mydomain.com) and I don't have shell access to run MYSQL commands, it looks like I have no other option but to nuke my entire Drupal installation and start from scratch recreating my pages - 100 hours of work, right down the crapper.
Or is there some other way I can fix this?
Comment #20
hass CreditAttribution: hass commentedDowngrade should help either.
Comment #21
philbar CreditAttribution: philbar commentedI downgraded the redirect module because of this error. I'm not sure if it's related, but around the same time my javascript aggregation has been broken. The files are being javascript files are being generated and I can view them in FTP. But my site gives 404 errors when anyone tries to access them.
I can't think of any other change that would cause this because I haven't been making many changes on my site. Just updating modules. I've searched for similar issues on Drupal.org and nobody else seems to have the same problem. That is why I believe it is related to downgrading this module, simply because many people haven't needed to downgrade it.
Comment #22
philbar CreditAttribution: philbar commentedThe fix in #14 works for me. I believe it should be added to the update script.
Comment #23
Kevin Hankens CreditAttribution: Kevin Hankens commentedOn a related note, redirect_path_update() appears to be creating a circular redirect when I create a redirect that mimics a url alias.
STR:
1. Create a node with a url alias, e.g. node/123 -> content/my-node
2. Create a redirect from node/123 -> content/my-node-1 (note the slightly different destination path)
3. Edit your node and change the url alias to content/my-node-1 (matches the destination path from step 2)
The redirect module appears to create a new redirect from content/my-node-1 -> node/123. This is done via redirect_path_update().
Is anybody else seeing this behavior?
Comment #24
Kevin Hankens CreditAttribution: Kevin Hankens commentedI like #18 and it seems to work well for my case. However, I wonder if we should prevent it from ever saving the reciprocal redirect in the first place.
Comment #25
Eric_A CreditAttribution: Eric_A commentedMy impression was that it created a redirect from content/my-node to node/123.
But yes, that amounts to the same thing: a looping issue for as long as the active alias from node/123 happens to be the same as the path the system was redirecting from.
There are multiple ways to get such direct redirects to self. The patches in this issue simply provide a last line of defense: if the target alias right now happens to be same as our original from path then don't redirect. If the code from damien_vancouver and me works for you, then your changing the status to RTBC would be welcomed. Others here have mentioned that it worked, so the time has come.
Comment #26
Eric_A CreditAttribution: Eric_A commentedOops, I said it wrong. Kevins scenario is one of those that could happen.
Comment #27
deetergp CreditAttribution: deetergp commentedI encountered this redirect loop issue on my site. I initially had some issues applying the patch in #18, it failed "git apply --check", until I realized that the repo was defaulting to the "master" branch rather than the "7.x-1.x" branch. Once I checked out the correct branch, the patch passed check, applied without issue and solved my redirect loop issue.
Though I don't want to presume that my testing definitively counts as "reviewed & tested by the community," it definitely worked for me. Thanks for the patch!
I will create a separate issue for getting the repo to default to the "7.x-1.x" branch.
Comment #28
Eric_A CreditAttribution: Eric_A commentedAfter applying both this patch and the global redirect patch from #905914: Merge global redirect functions into Redirect module it becomes apparent that the patch here (#18) needs a little work. A possible fix that comes to mind is passing in 'alias' => TRUE when normalizing the original URL.
Comment #29
xavier.carriba CreditAttribution: xavier.carriba commentedSuscribe
Comment #30
wiifmI have --dev + the patch in #18, and I can confirm that at least the error message goes away when repeating the node title change and then change back trick.
The only issue I foresee is that the redundant redirect still continues to persist in the database. I think there should be node_update() implemented to purge any redirects that now point away from the current $node URL.
Thoughts ?
Comment #31
azinck CreditAttribution: azinck commentedThe patch in #18 is working for me in fixing circular redirects. I support thinking through #1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect to see if we can prevent the problem in the first place. It's a difficult problem to solve.
Comment #32
rooby CreditAttribution: rooby commentedEither this issue or #1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect needs to be closed as a duplicate.
I would recommend leaving this one open and updating the first post to have all the info from the other one, because this one has more discussion and patches.
Comment #33
azinck CreditAttribution: azinck commented@rooby: I agree that there's a lot of overlap between the two issues.
I have a suggestion:
Discussion in this issue seems to have coalesced around "Stop circular redirects from redirecting infinitely". That's the problem the patches here try to fix, at least. Let's re-title this issue appropriately let it carry on.
#1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect has an unnecessarily specific title but is intended to be a broader discussion of how to stop circular redirects from being established in the first place. Personally I don't think that's feasible and have suggested a report-based solution but that's neither here nor there. I suggest re-titling that issue to something clearer. Perhaps "How to resolve conflicts and undesired interactions between url aliases and redirects".
Comment #34
rooby CreditAttribution: rooby commentedOh, I figured that this one was for fixing the underlying cause.
If it is about handing the infinite redirects that have been allow to be created, then this one should be closed as a duplicate of #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions
[EDIT] Maybe. At any rate, there are too many issues open for what is actually one single underlying issue (infinite redirects should not be created in the first place).
Comment #35
azinck CreditAttribution: azinck commentedI agree that there are a lot (perhaps too many) issues for one basic problem. But I'm not so sure #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions is an exact duplicate either (personally I think the flood detection code discussed there should be stripped out in favor of the patch in this issue).
This infinite loop, url alias collision problem is a fairly complex one without a single clear solution. Even your statement "infinite redirects should not be created in the first place" which seems self-evident on the face of it is perhaps not really so self-evident (see #1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect for some discussion of when we might need to preserve infinite redirects).
There probably needs to be a meta-issue established for the overall problem which can link to the various related issues and map an approach forward.
Comment #36
damien_vancouver CreditAttribution: damien_vancouver commented* #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions was the original issue and discussed rolling back the "Oops! This website caused a circular redirect" message.
* (As explained in #2 here), this issue was requested to hold a patch for preventing circular redirects from occurring. This issue has a patch that has been marked RTBC for a while and I've personally had it on a few production sites that were experiencing the issue. It prevents anonymous users seeing that message.
* Then following that issue we started #1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect, which was requested as a fork of this issue to deal with preventing the bad data that is the root cause of the problem. That issue's discussion has now become more focused on providing a report of bad links, which is really almost another approach again besides fixing the bad data.
Combining the discussion makes sense, but... this issue's patch fixes the error message, has test coverage of the bug, and has been RTBC for a while.
If it really is ready, it could be committed, and close(fix) it instead. That message showing up to anonymous users is a nasty bug that's very easy to trigger at best, or crippling to an existing site at worst.
Then #1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect, the youngest issue of the three, could be marked as duplicate of #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions (the oldest).
EDIT: i see it got marked Needs Work again... but we should still figure out how to get it committed... It seems close.
Comment #37
rooby CreditAttribution: rooby commentedThanks for the explanation.
I can see why there are some different issues.
The low hanging fruit that would be great is, like you say, making sure the end user doesn't see that message via the patch in this issue.
If there are other ways of triggering that message then another low hanging fruit would be related to #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions: Either removing that whole message code, or making it an error message instead of a status message and also potentially getting rid of the watchdog logging or making that aspect an option to turn on & off.
Then the harder parts of what to do with the underlying problem could be addressed at leisure.
My 2 cents.
Anyway, back on topic.
Comment #38
azinck CreditAttribution: azinck commentedActually, the low-hanging fruit would be getting a patch from THIS issue committed. As far as I can tell, the change in #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions is *mostly* pointless since making that change without also making the change from this issue means you could get truly infinite un-caught redirects and an error from your browser. But once the patch from this issue is committed the one from #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions could follow.
That is, unless I'm missing something.
Comment #39
rooby CreditAttribution: rooby commentedNo I don't think you're missing anything, that's the same as what I said, although I tend to not write so clearly sometimes.
Comment #40
azinck CreditAttribution: azinck commentedOops, sorry rooby, I see now that I didn't read your post closely enough.
Bottom line: this patch needs to go in first. It's by far the most important first step for solving this problem.
Comment #41
damien_vancouver CreditAttribution: damien_vancouver commentedOK then, I'll mark #1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect as a duplicate of #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions and post its relevant discussion there along with a summary of what we did.
To get this issue (the fix) back on track then, here's where we are at:
@Eric_A, are you around? Could you provide some guidance on what next or why it's apparent the patch needs work?
Comment #42
rooby CreditAttribution: rooby commented@damien_vancouver:
You can probably leave them both open.
After this one goes in #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions still needs to either amend or remove that message, and the #1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect issue is for trying to fix the cause of the infinite redirects. Or at least some of them. If possible.
Comment #43
Eric_A CreditAttribution: Eric_A commentedI marked the patch here NW because the implementation does not allow for redirecting a node system path to its alias, i.e. it will not allow for node/1 to be redirected to its alias. It should allow this. (And the other way around, too, I'd say.)
Comment #44
rooby CreditAttribution: rooby commentedI don't see why you would want to redirect node/1 to its alias? I can't think of a use case for that.
Use the globalredirect module if you don't want people hitting the node/1 page.
Although I could be missing something.
Comment #45
jwilson3It's really a shame this issue is being held up for nearly 2 months because of a separate issue for globalredirect module integration. I thought it was already agreed that there are a number of ways that infinite loops can happen. Thus it follows that the solution should be progressive, fixing one problem at a time and getting working code into dev, so we can keep pushing forward and finding and nailing down the other issues. This seems like a big enough issue to simply get it in and THEN worry about globalredirect integration. no?
Comment #46
Eric_A CreditAttribution: Eric_A commentedThe one problem we try to fix here is the "redirect to self loop". The patch from #18 does this *and* as an unwanted bonus it kills a subset of perfectly legal redirects. The global redirect issue helped identify this, but it does not hold up this issue in any way. This one just needs work (and apparently a new test assertion is needed). I'll try to find some time this weekend to see if the idea I mentioned earlier is any good.
Comment #47
azinck CreditAttribution: azinck commentedEric_A: If there are remaining problems with the patch in #18 (aside from issues with Global Redirect) can you elucidate them here? It's not clear to me what those problems might be just from reading through the comments. As it stands, #18 makes sense to me and is working for my use-cases.
Comment #48
Eric_A CreditAttribution: Eric_A commented@azink, I've described the problem in #43
Attached patch should do the main job *and* not break a redirect from a system path to its alias. Would you be able to do some testing?
Comment #49
DamienMcKennaHere's an update script I wrote to purge redirects that are causing an infinite loop:
I decided to do it as two separate steps rather than one large query so there can at least be some logging of the pages that were affected.
Comment #50
heddnPatch in #48 seems to resolve the issue. I tested using system path example.com/node/123 and redirect example.com/foo. Redirects are stopped. If I rename the path alias to foo2, then the redirect logic doesn't get fired, which is also appropriate. Let's get this thing committed.
Comment #51
heddnBTW, I like having #49 available but not included in redirect. Not so sure I want it in a hook_update_N that is provided by redirect because I want to be able to pick and choose which redirects should be deleted.
Comment #52
a.ross CreditAttribution: a.ross commentedHm, it also seems that removing redirects like that (#49) won't remove all possible loops. It just removes a redirect to itself.
On the other hand IMO some dedicated diagnostics interface just to find redirect loops is overkill - at least for now. It could always be added later if it turns out to be a popular request or something.
Comment #53
damien_vancouver CreditAttribution: damien_vancouver commented+1 for patch from #48 - it works great for me and prevents the Oops message. I've tested it on multiple produdction sites.
Since this issue is already marked RTBC, we need a maintainer for redirect module to do a final test and if it looks good, commit it.
Then 7.x-1.x-dev will at least contain the fix, for novice users who cannot apply a patch (ie. "most people").
re #49 and discussion in #50-52:
- The query should join on the "language" column as well or the join may be ambiguous on multilanguage sites.
- Fixing the bad data doesn't make the underlying problem go away. As soon as users are in there working and changing URL paths, then circular redirects start happening again in the database. It happens almost immediately in the Real World. But we already forked another issue to discuss that: #1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect, specifically for that discussion so it would not hold up the fix in this issue. So let's discuss it further or talk about update hooks and fixing / preventing bad data there. I will un-dupe it again, re-title it and paste the comments from #49-52 there for further discussion.
Let's please keep this issue focused on testing the patch in #48 and getting that patch committed ASAP! Does it need anything else? If not hopefully a maintainer will review and commit it soon.
Comment #54
a.ross CreditAttribution: a.ross commentedThe only thing I would like to add is that the infinite loop error message shouldn't sound that immature... :)
Comment #55
damien_vancouver CreditAttribution: damien_vancouver commented@a.ross:
That's actually discussed in the oldest of the three issues on this topic: #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions.
This issue was forked from that issue originally, as requested by a maintainer.
If this patch gets committed, then #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions could then become a cleanup of the message code, which won't get run any more and is no longer needed.
Meanwhile #1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect could focus on preventing/fixing bad data in the database, and everything would end up surprisingly neat and tidy.
Comment #56
joshf CreditAttribution: joshf commentedThanks for everyone's work on this.
I'm curious why this happens in redirect_redirect() instead of redirect_goto() where the header is actually set?
Thanks in advance; I'm still trying to figure out the standards for this stuff.
Comment #57
jdleonard#48 looks good and is working well for me. +1 RTBC
Comment #58
drupalerocant CreditAttribution: drupalerocant commentedIs the patch in #48 commited to the dev version? I ask because I see that the last development version is from february 6th.
Comment #59
dnotes CreditAttribution: dnotes commentedIt doesn't look like this has been committed yet. +1 for RTBC since this seems to solve a critical problem for many people. Not sure if there are other considerations for how this is done, but it would be nice to get some solution for this.
Comment #60
Alan D. CreditAttribution: Alan D. commentedStill needing tests I think, but this worked for us too.
We only noticed after Google AdWord links all generated the loops http://www.example.com/?utm=test
Comment #61
philbar CreditAttribution: philbar commentedCan we get this committed? I've ran into this problem again.
Steps to reproduce:
Expected Result:
Actual Result:
Comment #62
John Pitcairn CreditAttribution: John Pitcairn commentedIn moderated D7 workflows there is an additional fish-hook because there may be an extra node_save() call to set the "current" revision - see #1945558: Redirects incorrectly created when saving as draft (using pathauto/redirect default settings).
The patch at #48 does remove the resulting warning message (using latest redirect dev) when a redirect-to-self is viewed, but does not prevent the actual creation of the two additional redirects created at the "draft" stage mentioned in that issue. These are redirects from the current revision pathauto alias and a draft revision pathauto alias.
Comment #63
fenstratYet another +1 for RTBC.
This is a complex set of issues here, but the patch in #48 stops the bleeding with the warning message.
Comment #64
tamasd CreditAttribution: tamasd commentedHi,
I have created a bit more sophisticated solution. This also filters a longer redirect chain e.g.:
- foo -> bar
- bar -> baz
- baz -> foo
And this does not allow saving a redirect loop.
Comment #65
heddnThe patch #64 doesn't do anything about redirects that are created from the path alias side of things. #48 does account for that by not redirecting if someone creates a path alias that duplicates a redirect. I do like the idea behind this patch, but I think it should also incorporate more of what is in
#48 or redirects could still occur.
Comment #66
emilyf CreditAttribution: emilyf commentedsubscribe
Comment #67
yannickooPatch from #64 fixed that infinite loops for me, thanks!
Comment #68
attila.fekete CreditAttribution: attila.fekete commentedI rerolled patch #64 to match with 1.0-rc1. (also included #48 in this)
Comment #69
s_leu CreditAttribution: s_leu commentedI had the problem with infinite loops when in combination with automatic URL aliases. When i changed a node title and saved the node i was redirected twice on the same node and got the infinite loop message.
The patch in #68 fixed the problem for me.
Comment #70
s_leu CreditAttribution: s_leu commentedComment #71
plinto CreditAttribution: plinto commentedI have tried #48 and #68 and but niether help with #62, which what I am facing too.
Comment #72
sjugge CreditAttribution: sjugge commented#68 works with a simple test case (no loops can be created) which is already a big win from an editors or end-user POV.
One minor annoyance is that a user enters his or hers content, gets the warning message and then goes of to remove any aliases which may cause the loop. This action will cause them to leave the node edit page and loose their content changes.
Comment #73
vinmassaro CreditAttribution: vinmassaro commentedTested #68 against 7.x-1.x-dev and it gets rid of the redirect loop message.
We have a few hundred sites and this always happens when users are creating content, and it is confusing for them. Would be great to get some fix for this committed. Thanks!
Comment #74
hass CreditAttribution: hass commentedDave asked for critical issues in the queue. Setting priority.
Comment #75
Dave ReidI never *asked* for critical issues hass, so do not put words in my mouth EVER. I agree this is a high priority to fix, but this is something that I still consider major. I have time today set aside to look at it.
Comment #76
hass CreditAttribution: hass commentedIf the module is broken we name this critical.
Comment #77
DamienMcKenna@hass: It doesn't happen on every install, therefore it isn't critical.
Comment #78
hass CreditAttribution: hass commented500.000 pathauto installations are out there. This is over 50% of all drupal installations compared to 53.000 redirect rc1 installations. No good chances that we have a countable number of sites not affected. This brings us nowhere. This is critical as I need to downgrade.
Comment #79
DamienMcKenna@hass: Nobody's stopping you from using the patch, and following smart development practices like Jen Lampton documented back in March you can easily track the patch. Dave said he was going to try looking at it today, please give him the time to do so.
Comment #80
lmeurs CreditAttribution: lmeurs commentedMy temp fix is the following: I used a Pathauto hook which is triggered whenever a new alias is created, updated or read by Pathauto. The hook checks whether the current node has redirects with the same alias as the current node's new alias. If so, it deletes these redirects from the database table.
Comment #81
jenlamptonPatch from #68 still applies cleanly.
Comment #82
Elijah LynnI refactored #80 and submitted a new issue to Pathauto. #68 created some issues for me (sorry I forgot what they were) and most importantly still kept a Redirect rule that was the same as the new alias which I don't think is very clean.
The patch for Pathauto is here https://drupal.org/node/2065091#comment-7754273
Comment #83
GoZ CreditAttribution: GoZ commentedKeep an eye on https://drupal.org/node/1817976#comment-7753335. It seems to be more simple and patch works fine.
on hook_path_update or hook_path_insert, if a redirect with the new path already exists, it's deleted. That's all. No patch needed for pathauto nor heavy tests.
Comment #84
Elijah LynnThanks GoZ, the patch in #83 works in my tests and my patch for Pathauto (#82) got closed in favor of the work being done in Redirect anyways.
Comment #85
plinto CreditAttribution: plinto commented#83 seems to be working, and it works with moderation
Comment #86
acbramley CreditAttribution: acbramley commented#83 works well and stops circular redirects created by changing a node's alias back to one that previously existed should we close this as a duplicate, the patch at https://drupal.org/files/redirect-prevent_circular_redirects_in_hook_pat... is much lighter and a better approach IMO
Comment #87
Alan D. CreditAttribution: Alan D. commentedUm, that issue assumes that the circular redirects are all due to the generated path aliases doesn't it?
I managed to trigger this via Google AdWord links with #905914: Merge global redirect functions into Redirect module. So from my (poorly researched) perspective:
#1817976: Updating an entity with an URL alias that matches an existing redirect causes bad data and circular redirect = Keep the entity path alias tables clean
This issue = Sanity check / fallback if the s** hits the fan
;)
Comment #88
hass CreditAttribution: hass commentedAnother 4 weeks passed away what is far longer than "today".
Comment #89
heddnLet's get an update to the issue summary, see: https://drupal.org/issue-summaries
Comment #90
acbramley CreditAttribution: acbramley commentedNew patch in #68 is definitely an improvement. Updating to that stopped aliases being created that had redirects from them (very confusing)
Comment #91
Dave ReidPatch needs to be re-rolled against current 7.x-1.x.
Comment #92
swentel CreditAttribution: swentel commentedHrm, this applies cleanly here. Tested it manually: you don't get a redirect or a message of infinite loop.
However, in the patch I see a form error, but wasn't really able to trigger it, so not sure exactly where to go next.
Comment #93
swentel CreditAttribution: swentel commentedUpdate: could get the form error now too (I finally understand the flow), so this is ready to go for me.
Comment #94
Kristen PolI just applied #68 and it worked well for me and prevented getting into a redirect loop. RTBC++ Thanks!
Comment #95
Eric_A CreditAttribution: Eric_A commentedThe tests for #48 (and #68) were broken by http://drupalcode.org/project/redirect.git/commit/ad09f6c.
Also, I'm pretty sure that #68 is broken for multilingual sites and for any non-trivial URL (i.e. with URL options). The patch in #68 is sophisticated and thus needs sophisticated tests. Let's please create a separate issue for that and fix the simple (and probably most frequently occuring) scenario first.
Comment #96
Eric_A CreditAttribution: Eric_A commentedPasted Issue Summary template. Added related issues to the Issue Summary.
Can't do more right now. We could probably do with summarizing the two patches by describing pros and cons and who reviewed, tested and plussed one those.
Comment #97
swentel CreditAttribution: swentel commented#68: redirect_loop_detection-1796596-68-reroll.patch queued for re-testing.
Comment #98
swentel CreditAttribution: swentel commentedThen we need more people testing instead of a gut feeling. Note, I've actually tested on a multilingual site and worked perfectly.
Comment #99
Eric_A CreditAttribution: Eric_A commentedThe patch in #68 passed after re-testing and that was expected. The point is that the patch in #68 (and this goes for #48 as well) needs an accompanying test only that will fail on the new assertions. (One of them is broken now and will pass instead of fail.)
As for the extra tests that are needed for the sophisticated part of #68. Indeed, it's not my initial analysis or gut feeling that matters. It's up to the patch makers to add automated tests for at least all normal use cases, including cases that start out with the state when there are URLs with the same path but different languages. The point is that it should not detect a loop when there is a target URL with the same path but a different language than the one we're redirecting too. If the logic in #68 really works it might be the perfect replacement for the detection that is being removed in #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions.
Comment #100
tiki16 CreditAttribution: tiki16 commentedTried to apply the patch "redirect_loop_detection-1796596-68-reroll.patch" and it partially patched (Cannot apply hunk @@ 10 ) using netbeans
Comment #101
Vemma-1 CreditAttribution: Vemma-1 commentedThe only way after trying many patched was to open the redirect.module file and omit line #989
/** drupal_set_message('Oops, looks like this request tried to create an infinite loop. We do not allow such things here. We are a professional website!'); */
Comment #102
generalredneckJust an observation. After doing a git biscect after reproducing the symptoms, It sent me to the following commit.
Comment #103
hanoiiI wonder if anyone tried patch #1936820-7: Auto-redirect doesn't check for old aliases, it seems a pretty simple patch and it should fixed this issue, I pretty sure it's almost a duplicate of the other one and the patch seems nicer.
Comment #104
stefan.r CreditAttribution: stefan.r commentedThe patch in #103 won't fix aliases that are already broken, so something like #48 would still be needed.
Patch attached that combines the two, with updated assertions in the test that work against the current 7.x-1.x as per #91.
Comment #105
yannickooWhy did you add that empty line?
Please add a space after the comma and put the string in double quotes so that you don't have to escape some parts.
Comment #106
stefan.r CreditAttribution: stefan.r commentedComment #107
stefan.r CreditAttribution: stefan.r commentedComment #108
alexweber CreditAttribution: alexweber commentedJust tested and #106 works for me.
Comment #108.0
alexweber CreditAttribution: alexweber commentedUpdated issue summary.
Comment #109
Owen Barton CreditAttribution: Owen Barton commentedThis patch is working for me also, handling existing and preventing new "back-and-forth-rename" redirect loops. Code looks good, and tests pass so RTBC.
Comment #110
fenstratAlso confirming the RTBC status of #106.
We've used the patch in #48 in production for quite a while, #106 improves on it by removing existing redirects on update if they match the new alias.
Would be great to see this committed.
Comment #111
fenstratMarked #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions as a duplicate of this.
Comment #111.0
fenstratPasted template. Added Related Issues. It's a start.
Comment #112
fenstratUpdated issue summary.
Comment #112.0
fenstratUpdated issue summary.
Comment #113
jyee CreditAttribution: jyee commentedAdding a +1 to #106. This patch worked well for me.
Comment #113.0
jyee CreditAttribution: jyee commentedUpdated issue summary, adding related issue #1936820
Comment #114
acrosmanPatch in #106 worked for me.
Comment #115
fenstratReverting changes, I assume these somehow got reset on the d.o D7 upgrade.
The patch in #106 is still very much RTBC.
Comment #116
caspervoogt CreditAttribution: caspervoogt commented#106 looks good. Tried it but ran into some errors... tried both the 7.x-1.x and master branches.. not sure which of those corresponds to 7.x-1.x-dev.
In case it means anything to some of you, here's the error I got;
Perhaps Redirect could also (in addition to #106?) check for infinite loops when cron runs, and then delete them. I wrote a sandbox module that does this; https://drupal.org/sandbox/plethoradesign/2138793.
Comment #117
fenstrat@plethoradesign The patch in #106 applies cleanly to redirect-7.x-1.x-dev for me.
As for cleaning up existing infinite loops, I agree it's a good idea. However given this issue has been going on for so long and we've finally got some consensus on the patch in #106 as the way to fix creating new infinite redirects (as well as removing them if they exist on path update). I think we should get this in first. Removing existing ones should probably be a follow up issue.
Comment #118
caspervoogt CreditAttribution: caspervoogt commented@fenstrat, I totally agree #106 needs to get in first. My sandbox module has been tiding me over in terms of dealing with existing ones. Will follow up once #106 is committed.
Comment #119
deviantintegral CreditAttribution: deviantintegral commentedComment #120
deviantintegral CreditAttribution: deviantintegral commentedThe above patch is combined with the patch from https://drupal.org/comment/7805833#comment-7805833 as they both covered removing duplicate redirects on entity updates. If it passes tests I'd like to close that issue as a duplicate.
Comment #121
deviantintegral CreditAttribution: deviantintegral commentedComment #122
stefan.r CreditAttribution: stefan.r commentedFor reference I will post an interdiff between #119 and my patch in #106.
The difference seems to be that #119 also runs the deletion check upon
hook_path_insert
instead of only onhook_path_update
, and goes about the deletion differently. The deletion has seemingly the same result; unless multiple redirects with the same problematic source exist, in which case it will delete all of them instead of just a single one.Looks good to me! :)
Comment #123
fenstratThe changes in #119 look good. Thanks for the interdiff in #122 @stefan.r
This comment should be the same as it is below for consistency:
Delete all redirects having the same source as this alias.
With that done I can RTBC this.
Comment #124
stefan.r CreditAttribution: stefan.r commentedComment #125
fenstratConfirming that #124 is RTBC.
Comment #126
j0rd CreditAttribution: j0rd commentedJust installed -dev, with patch 124 and it resolve the warnings with regards to #2105063: Oops, looks like this request tried to create an infinite loop. We do not allow such things here. We are a professional website!
Comment #127
alexweber CreditAttribution: alexweber commentedWoohoo! Can we get this committed?
Comment #128
aze2010 CreditAttribution: aze2010 commentedplease commit!
*subscribing*
Comment #129
whthat CreditAttribution: whthat commentedBangin, #124 is wonderful with Workbench Moderation. I owe everyone a drink.
Comment #130
quagmire CreditAttribution: quagmire commentedI 2nd (or 3rd or 4th) -- please commit! Thanks for the great work on this.
Comment #131
Leeteq CreditAttribution: Leeteq commentedand 5th... - time to commit this to -dev.
Comment #132
anavarreYup, tested #124 just now with one or several redirects and it works as advertised always.
Comment #133
Leksat CreditAttribution: Leksat commentedJust want to warn you about MySQL collation. By default it's utf8_general_ci (I don't know from where this coming, from Drupal or from MySQL itself). And, in this case, MySQL make no difference between umlaut symbols and them "normal" analogs. This basically means that, for example, "é" = "e".
Because of this peculiarity I met redirect loops. After installing the transliteration module, I got a record in the redirect table with "personnalisées" source and "personnalisees" redirect. And this query (simplified)
returned that record.
To resolve this I had to change the collation of the source field to utf8_bin.
This issue may happen in redirect_delete_by_path() function, so correct redirect record may be deleted.
Comment #134
vegardjo CreditAttribution: vegardjo commentedI can also confirm that 124 works
Comment #135
SylvainM CreditAttribution: SylvainM commentedThis patch is great, thanks.
I think a hook_update_N would be useful to remove bad data from the db.
What do you think about this attached patch ?
Comment #136
drupov CreditAttribution: drupov commentedCool, #135 solves the issue for me (no infinite loop after setting the path back to the original path)
Comment #137
Dries ArnoldsI tested #135 and it works for me.
Comment #138
mahaprasad CreditAttribution: mahaprasad commentedI have applied patch #135 & it is working fine for me.
Comment #139
RoloDMonkey CreditAttribution: RoloDMonkey commentedI am changing the status back to "Needs review". At this point, it is not clear if we should be committing the patch in 119, 124 or 135.
Comment #140
RoloDMonkey CreditAttribution: RoloDMonkey commentedComment #141
stefan.r CreditAttribution: stefan.r commented#124 is just #119 with a correction of a comment as pointed out in #123
All #135 is, is #124 with an update hook (which seems OK to me).
So #135 seems the most complete and is probably the one that should be committed.
Comment #142
RoloDMonkey CreditAttribution: RoloDMonkey commentedThank you for the explanation.
Has anyone tested the update hook? We don't want to accidentally delete valid redirects.
Comment #143
fenstratI've not yet tested the hook_update_n() addition made in #135. However at first glance:
Missing trailing period.
Shouldn't this be redirect_update_7001()?
No need for this comment.
We don't usually concatenate variables in Drupal. $rids_to_delete would probably be better.
Due to the possibility of many existing redirects I can understand why you've done and 'IN' query here. Not yet tested it for performance, but I think the theory is sound.
'redirect was deleted' => 'circular redirect causing infinite loop was deleted'.
Needs to mention 'circular redirect causing infinite loop' as above. Also missing trailing period.
Comment #144
DamienMcKennaRegarding the update script's number, per the hook_update_N documentation, 71xx updates are for update that match to v7.x-1.x of the module, 70xx updates are for the "initial porting of your module to a new Drupal core API" which does not apply here.
Comment #145
fenstratBaah, brain fart on my behalf. Thanks for clearing that up Damien.
The rest of my nit picks still apply from #143.
Comment #146
SylvainM CreditAttribution: SylvainM commentedThanks for the review, I think all points are fixed in attached patch.
Please test and review :-)
Comment #147
fenstratGreat, thanks @SylvainM.
I've tested the update hook on a few sites and it works as expected.
The general approach here was RTBC back in #109. The addition of the update hook to remove existing circular redirects makes sense. So marking this as RTBC yet again. This is good to go.
Comment #148
Dries ArnoldsTested patch in #146 on a test site with several scenario's that used to cause an infinite loop. After that went well I am now running it on a production site for a few days. Had no trouble. So imho also RTBC.
Comment #149
Pere Orga#146 works for me too
Comment #150
mrmikedewolf CreditAttribution: mrmikedewolf commented#146 fixed a recurring issue we were running into on one of our projects. Thank you much!
Comment #151
MurzConfirm that #146 fixes this issue for my sites too.
Comment #152
tonylegrone CreditAttribution: tonylegrone commentedI also confirm #146. Thanks!
Comment #153
johnennew CreditAttribution: johnennew commentedBrilliant - I can confirm this works!
Comment #154
ChrisGrewe CreditAttribution: ChrisGrewe commentedConfirmed working for me as well.
Comment #155
sanduhrsWorks as advertised +1
Comment #156
ckng#146 tested working.
Comment #157
nwehner CreditAttribution: nwehner commented#146 fixed *several* infinite redirect loops I had inadvertently created on my site - many thanks for this! Pushing it over to my live environment now :)
Comment #158
candelas CreditAttribution: candelas commented#146 installed for some hours and it works. if i have problems, i will come back and report. thanks a lot to the people that fixes bugs :)
Comment #159
ChaseOnTheWebComment #160
ChaseOnTheWebHmm, apparently I have to uncheck the "hidden" ones too.
Comment #161
pontus_nilsson#146 works well for me.
Comment #162
sch2 CreditAttribution: sch2 commentedThanks SylvainM for the fix (#146). Just applied the patch and worked perfectly.
Comment #163
narendraR146: redirect.circular-loops.1796596-146.patch queued for re-testing.
Comment #164
drummThis hit us on Drupal.org: #2274715: Changing name and then back again caused infinite loops to be created
Comment #165
quotesBro CreditAttribution: quotesBro commented#146 works for me too, thanks.
Comment #166
rwohlebSeems like this has been accepted by the community, so let's get it committed.
Comment #167
wwhurley CreditAttribution: wwhurley commentedTested it with a couple of sites and it appears to have resolved the issues we were experiencing. RTBC for me, too.
Comment #168
Pere OrgaI just created #2300419: Is this module still maintained?
Comment #169
heddnComment #170
thedavidmeister CreditAttribution: thedavidmeister commentedworks for me too. Please commit this.
Comment #171
rcodina CreditAttribution: rcodina commentedIt also works for me!
Comment #172
tannerjfco CreditAttribution: tannerjfco commentedSame as #146 but with bump to hook_update function to 7101, as fix for #2051313: uid not stored when redirects added via Add Redirect page is now committed to dev and uses 7100
Comment #173
loparr CreditAttribution: loparr commentedhi,
I see that changes are made to .install file as well. So is it advised to uninstall module first and then install patched module? Uninstalling would remove database entries and that I do not want.
So I patched all other files except .install file and it is working.
Should I be worried about .install file? Thank you.
Comment #174
Alan D. CreditAttribution: Alan D. commentedNo, just run update.php and it will run these functions.
Comment #175
loparr CreditAttribution: loparr commentedAfter patching current dev with #146 and running upgrade I get error:
Fatal error: Cannot redeclare redirect_update_7100() (previously declared in .../sites/all/modules/redirect/redirect.install:271) in .../sites/all/modules/redirect/redirect.install on line 389
Patch #172 works against current dev version.
Just to make sure - so which patch against what version is advised?
Thank you.
Comment #176
pjcdawkins CreditAttribution: pjcdawkins commented@loparr
Patches should always be against the current
-dev
version.Here is the difference between #146 (which has been RTBC for a long time) and #172:
This is a trivial yet essential update. So we can assume #172 is RTBC.
Comment #177
rooby CreditAttribution: rooby commentedHiding the old patch.
Comment #178
jwilson3Issue was reported exactly 1 year and 11 months ago, as of yesterday. Can we beat the 2 year mark!?!
Comment #179
thedavidmeister CreditAttribution: thedavidmeister commentedI'd totes commit this myself if I could.
Comment #180
CatherineOmega CreditAttribution: CatherineOmega commentedWant to open a ticket requesting to be a comaintainer, thedavidmeister? :)
Comment #181
thedavidmeister CreditAttribution: thedavidmeister commentedI hope it doesn't come to that, I wish there was a way to "escalate" a ticket without needing to apply for co-maintainer.
Comment #182
Honza Pobořil CreditAttribution: Honza Pobořil commented#172 works
Comment #183
parasolx CreditAttribution: parasolx commentedconfirm that #172 works. tested on large site with 10000+ content.
i think should it deploy into release version since a lot of site having the same problem.
Comment #184
Alan D. CreditAttribution: Alan D. commentedThe community have had a very strong voice here, something that I can only dream about in my own projects ;)
Push to dev, and start child issues for following up tasks? If unsure, tag a new release and then commit to dev? It would nice to see this resolved before Drupal 8 is released.
IMHO, this and #905914: Merge global redirect functions into Redirect module would be blockers issues to determine the base functionality that would be used as the milestone for doing the Drupal 8.x port.
Comment #185
heddnIf we were to read back through the history of this issue, a version of the patch has been RTBCed for over a year. With several, I mean several, confirmations. Can this just get committed?
Comment #186
DuaelFrThis patch must be in about all the makefiles of the planet. It's time to push it to the dev release at least!
It has an upgrade path so it's safe and the code is well optimized so d.o would not suffer from this awesome fix.
Please! Please! Commit.
From France with Love.
Comment #187
Leeteq CreditAttribution: Leeteq commentedYes, please push it at least to -dev.
Comment #188
SGhosh CreditAttribution: SGhosh commentedPlease push it to some version. Everyone needs to keep applying this patch. #172
Comment #190
thedavidmeister CreditAttribution: thedavidmeister commentedI have put my hand up to be a co-maintainer and apply some of the outstanding RTBC patches in the queue #2342117: Application for co-maintainer: thedavidmeister.
Comment #191
deanflory CreditAttribution: deanflory commented#172 appears to have applied whereas#146 had the WSOD error.
Here's the patching results from #172 when applied to 7.x-1.x-dev after running the "redirect-drupal-subdirectory-fix-1198028-13.patch" patch:
patch < redirect.circular-loops.1796596-172.patch
patching file redirect.install
Hunk #1 succeeded at 363 (offset 7 lines).
patching file redirect.module
Hunk #1 succeeded at 376 (offset -18 lines).
Hunk #2 succeeded at 392 (offset -18 lines).
Hunk #3 succeeded at 843 (offset -18 lines).
Hunk #4 succeeded at 1006 (offset -28 lines).
patching file redirect.test
Comment #192
Dave ReidCould just use $rid_to_delete = $query->execute()->fetchCol();
Should this be using redirect_delete_multiple()?
This is interesting. I wonder if it would be better *not* to delete existing data, and instead just make it not work and allow the alias to work. I don't feel great about deleting manual redirects/data.
This feels a little bit like the wrong location for this code. Should this be in path_redirect_alter() (as an implementation of hook_redirect_alter() for core's path.module)?
Missing spacing between the parameters here.
Same here.
Comment #193
Dave ReidWould it help if we could change redirects into some kind of 'disabled' state when this happens? I'd really rather not delete.
Comment #194
vinmassaro CreditAttribution: vinmassaro commented@Dave Reid: we see this issue happen only as described in #1, and the redirects created are never needed and need to be manually deleted to fix the bug. What's the use case for keeping them around, but disabled?
Comment #195
azinck CreditAttribution: azinck commentedI agree with Dave Reid about keeping the redirects around. All it takes is a content editor unwittingly setting an alias that collides with some important redirects and the redirects are silently killed, never to be seen again.
I'd rather see logic implemented that prefers to serve the page with the alias if there's a collision, but doesn't delete the redirects.
Comment #196
heddnre: #192.2
Can we do what commerce did recently? Way back in #51 I voiced caution about deleting redirects.
I really don't want us to bikeshed on this, as some version of a patch is in about every install profile that exists. What is the best path forward? I'd say we remove the hook_update_N and punt that to a follow-up.
Comment #197
heddnOpened the follow-up @ #2343755: Follow-up: Fix existing bad redirect data to address #191.2
Comment #198
azinck CreditAttribution: azinck commentedI'm with heddn in #196, but I'd say we need to not only remove the hook_update_N but also the calls to redirect_delete_by_path() in redirect_path_update() and redirect_path_insert().
Comment #199
Dave ReidCorrect, those calls I'm also concerned about. Just moving the update hook doesn't solve it.
Comment #200
drummWe haven't had any problems, at least that I know about, on Drupal.org, after running this on Drupal.org for a few weeks. That said, having the disabled redirects kept around would be a big help, if there were any problems. I think adding a disabled state for redirects would be a separate issue, which needs to be resolved before this.
Comment #201
Charles BelovIf there's a collision, why doesn't the new redirect add -0, -1, etc.?
We really can't know which side of the collision to disable, the original or the new.
Comment #202
GoZ CreditAttribution: GoZ commentedDon't understand why you don't want delete redirects which are not needed anymore.
Redirect is made for SEO and to be sure old path can be hit and return to right page (so new path).
If an another page build a path which is same as a redirect, redirect is no needed anymore and should be removed. Next time this path will be updated, a new redirect will be created to redirect to this new one.
Keeping old redirects disabled instead of deleted can be only useful for history, and to have a redirect table bigger (and so lower).
Comment #203
cmseasy CreditAttribution: cmseasy commentedI agree with GoZ.
My advice:
Comment #204
azinck CreditAttribution: azinck commentedI disagree with #202 and #203. Circular redirects are solved without the deletion of colliding redirects. You can remove that bit *and still have circular redirects solved*.
Especially on large sites with lots of editors I think it's bad policy to silently delete content (redirects) when people save nodes with colliding path aliases. I should not have to be nervous that creating some test page with any old path I might choose (or might have chosen for me by the pathauto settings) might, without my knowing it, deal hard-to-recover-from damage to someone else's carefully crafted redirects.
I understand that some (many?) people want the Redirects cleaned up. But I do not think that should be the default behavior. Redirect does not currently try to clean up collisions and adding that goes beyond the scope of what's needed to fix the actual problem at hand.
Comment #205
GoZ CreditAttribution: GoZ commentedRedirect aren't real content but 301 to not loose users and seo.
Right now, creating node with title which will make same path as existing redirect will generate this path but never be reachable. Redirect take hand so we will never can access this node.
If we take consideration of your example: you create some test page with same path as existing redirect.
1\ Right now, you're page will never be available on your path, redirect will redirect to old page.
2\ If redirect is deleted, you're page will be available. If you delete your page, redirect will be lost (that you don't want).
3\ If redirect is disabled, you're page will be available. If you delete your page, redirect can be enable, but only if there is one redirect. What's happened if there is other disabled redirect with this path ? Which one do you want to enable ?
For 2 and 3, you must also take care of unpublish content. If you create page with same path as redirect and this one is deleted or disabled, until content is published, users will see an 'access denied' on this page.
Another solution will be:
4\ Never allow to create same path as existing redirect. If redirect exists, set -n+1 to path like pathauto already does with path collisions.
Comment #206
azinck CreditAttribution: azinck commentedI'd prefer your option #4 to ensure that you can't create aliases or redirects on the same path as an existing redirect, but I don't think that's really tenable. There are many possible ways to create aliases and this would require API changes.
You are considering too narrow a use-case. On some sites redirects *should* be considered as content. Many sites use redirects to map multiple paths to a single node for SEO, marketing, or other content strategy purposes. Some sites may even use redirects in this way to maintain url mappings from old systems (pre-Drupal) to new content locations.
Comment #207
GoZ CreditAttribution: GoZ commentedHere some patch to not delete old redirects. During path insert or update, also check redirect, and re-generate another alias if redirect already exists.
Take care of pathauto.
This can be improved adding hook_update to take care of old redirects conflicts but it will be good to have your comments, and to know if this solution is better for you.
Comment #208
azinck CreditAttribution: azinck commentedThanks, GoZ. I appreciate you taking the time to do this.
I think this is a feasible solution though it may still be confusing to some content editors. I'm curious to hear from others.
I'd probably prefer the following solution:
* Allow redirect/alias collisions
* Attempting to access a path on which there is a collision should result in Drupal preferring the alias. (the redirects should be effectively ignored).
* Page that is ultimately served should have a notice set at the top that there are existing redirects that conflict with this path, and provide links to go repair. This notice could be limited to users with ability to edit the node or those with permission to administer redirects.
The doesn't interfere with existing workflows but prevents loops and provides users with the info the need to fix any collisions.
Comment #209
hitesh.koliCan someone confirm if the redirect.circular-loops.1796596-172.patch is in the recommended version ?
Comment #210
deanflory CreditAttribution: deanflory commented@hitesh.koli, the "recommended" version 7.x-1.0-rc1 is from 2012 and the patch in #172 is from 3 months ago, therefore it is not in the recommended version.
It's probably not in the 7.x-1.x-dev from 2014-Jul-23 since the #172 patch applies to that dev version (see my results in #191) without stating it is already in there.
Comment #211
stefan.r CreditAttribution: stefan.r commentedComment #212
stefan.r CreditAttribution: stefan.r commentedComment #215
stefan.r CreditAttribution: stefan.r commentedThis is a first stab at incorporating Dave Reid's feedback to the patch in #172 and allowing aliases to be disabled (not tested in production yet!). Before I work on this further perhaps someone can do an initial review?
I hadn't seen #207, sorry GoZ if I duplicated work here.
Comment #217
stefan.r CreditAttribution: stefan.r commentedUpdated tests
Comment #219
stefan.r CreditAttribution: stefan.r commentedAnd that last update had a typo :)
Comment #220
stefan.r CreditAttribution: stefan.r commentedThis is green now, so please can anyone review the patch in #219?
Comment #221
davidneedhamThe patch in #219 applies cleanly and the db updates do too. I can confirm that it stops existing circular redirects and keeps them from being created.
Comment #222
hanoiipatch #219 worked for me as well on an old site, that after upgrade, was triggering infinite loops.
Comment #223
Steven Jones CreditAttribution: Steven Jones commentedThis patch doesn't quite work for me:
I think this needs to set the status to 0, which is the disabled state, rather than 1.
This would also suggest that the tests added by the patch are insufficient. I did the following:
With the patch in #219 this left the redirect created during step 2 in tact, because of the above bug. I think we need to assert that not-only that we didn't get a circular redirect, but that we get the right page.
Comment #224
Steven Jones CreditAttribution: Steven Jones commentedRight. Here's a patch that changes the 1 for a 0, and adds a new test method to make that my test case is covered, and that that fix is picked up.
I think that that it breaks one of the existing tests though, but I'm not sure why.
Comment #226
Steven Jones CreditAttribution: Steven Jones commentedAh okay, this is because in
redirect_path_update
we try to see if the redirect exists in the DB already, by callingredirect_load_by_hash
Comment #227
Steven Jones CreditAttribution: Steven Jones commentedActually, there's no reason to not load disabled redirects when calling
redirect_load_by_hash
that I can see.So here's a patch that removes that condition from the query.
Comment #228
stefan.r CreditAttribution: stefan.r commentedThanks Steven, that 1 was obviously supposed to be a 0 :)
As to removing status from "load by hash", that makes sense indeed. We shouldn't want to be able to create a new redirect with an existing source, even if that old redirect is marked as disabled).
I have made some further refinements to this patch:
a) Moved Enabled checkbox to sit under Language dropdown and a added a help text.
b) By removing status from load_by_hash we are implicitly disallowing people to create any new redirects if another disabled redirect with that same source already exists. Added that same check elsewhere:
c) Changed wording from "The base source path %source is already being redirected" to "A redirect already exists for the source path %source.". This as this existing redirect might be disabled, at which point the source is not actually "already being redirected".
d) Hid disabled redirects under "Redirects" tab in the node edit screen.
One catch I did make (which is still an issue in all of the patches here) is that if you:
1. edit a node and change a URL alias from
first-alias
tosecond-alias
2. edit it again and change the alias back to
first-alias
(where upon submission thefirst-alias
redirect is disabled to prevent a circular redirect)3. edit it again and change the alias back to
second-alias
......going to
first-alias
will give a 404 as the redirect is still disabled. I am not sure there is an easy fix for this though as we can't distinguish between automatically or manually disabled redirects.Comment #229
stefan.r CreditAttribution: stefan.r commentedComment #232
Steven Jones CreditAttribution: Steven Jones commentedI think I'd expect redirect module to always try and put a redirect in place if I'm changing the alias, and that's what its configured to do.
In this case shouldn't we just always attempt to add an active redirect unless there's one there already, and it's enabled?
Comment #233
stefan.r CreditAttribution: stefan.r commentedFixed a typo in the code
Comment #234
stefan.r CreditAttribution: stefan.r commentedSo you're saying to "add an active redirect" if the existing redirect is already disabled, right? That could work.
My worry was:
a) having multiple (disabled and enabled) redirects with the same source in the database, where only one can be enabled at the same time -- which seemed troublesome to implement
and b) annoying users who had manually deactivated a redirect by reactivating it again. But upon further thought, manually disabling those specific redirects sounds like an extreme edge case, and as you well note adding those redirects is what the module is configured to do. If anything we could add a warning that we just automatically reactivated a disabled redirect, but it's hard to not make that message seem cryptic and irrelevant to the large majority of users.
So if by "add an active redirect" you mean update the existing redirect and make it active, yes that may make sense.
Comment #235
Steven Jones CreditAttribution: Steven Jones commentedYeah, so if there's an existing redirect with the same hash, but just disabled, then we should just re-enable it, because that's really what the user wants, it doesn't matter who disabled it.
Comment #236
stefan.r CreditAttribution: stefan.r commentedComment #237
vinmassaro CreditAttribution: vinmassaro commentedPatch in #236 worked for me. It successfully disabled the redirects that caused infinite loops.
Comment #238
stefan.r CreditAttribution: stefan.r commented@vinmassaro good to hear! Anyone else care to review?
One little UI thing I was wondering about is in the redirect administration screen (
admin/config/search/redirect
) the patch lists "disabled" redirects whereas on the node edit screen it hides disabled redirects (in the "URL redirects" tab), assuming content managers would usually just be confused by disabled redirects, especially if they're disabled automatically to prevent a circular redirect. Does this make sense? Perhaps we should add a little snippet to the tab that says only enabled links are listed?Comment #240
kingofdeal CreditAttribution: kingofdeal commentedCan anybody help me or guide me how to install this patch.
Because I am 100% New. and only thing I know how to install directly on admin panel modules and theme..
Please help me. thanks
Comment #241
tripper54 CreditAttribution: tripper54 commented@kingofdeal, try https://www.drupal.org/project/redirect/git-instructions .
You'll to install git if you haven't already.
Comment #242
Steven Jones CreditAttribution: Steven Jones commented@stefan.r yeah I think it's a bit weird that we don't list disabled redirects on the entity forms, so here's a patch that does, I think that makes it much clearer what's going on. I've also added 'bulk operations' for 'disabling' and 'enabling' as that might be a useful thing to do on the admin listing page.
Attached also is an 'only tests' patch so that we can make sure that our tests actually test for something that isn't working in the current code.
Comment #244
Steven Jones CreditAttribution: Steven Jones commentedSorry, that 'only tests' patch was invalid. Here's a better one.
Comment #246
Steven Jones CreditAttribution: Steven Jones commentedAwesome, so the patch to review is in #242 and is nice and green. All working for me too.
Comment #247
stefan.r CreditAttribution: stefan.r commented@Steven Jones
"Enabled" :) I also wonder if we should run the hook_redirect_enable_multiple API hook on nodes that are already enabled if enabled nodes are in the function argument of redirect_enable_multiple()? We may want to test if any of the nodes had been enabled already when invoking the enable API hook. Same for the disable API hook, where we'd want to test for nodes that are already disabled and skip those.
Also, the summary in the vertical tabs says "3 redirects" if there is 1 enabled redirect and 2 disabled redirects -- perhaps it should say how many redirects are enabled/disabled?
Otherwise looks good.
Comment #248
trrroy CreditAttribution: trrroy commentedThis worked for me too. Right after running the update, when I first checked the list of redirects it appeared all were Disabled. I clicked through to edit one and noticed it was Enabled so I cleared cache and then all showed in the list as Enabled (actually a few were disabled as they should be after the update).
Comment #249
stefan.r CreditAttribution: stefan.r commented#242 with feedback from #247 included.
Please can we get some further reviews so this can get back to RTBC?
Comment #250
elmertoft CreditAttribution: elmertoft commentedPatch in #249 works well for me.
Comment #251
pjcdawkins CreditAttribution: pjcdawkins commentedTested #249
Comment #252
stefan.r CreditAttribution: stefan.r commented@pjcdawkins, thanks!
Comment #253
vinmassaro CreditAttribution: vinmassaro commentedWe're having this problem on many sites and the patch in #249 fixes the issue. This patch updates the database so we are a little hesitant to apply it if the patch could change again when the maintainer reviews it. Hoping it gets committed as is with any changes going forward just being code changes, not database. Thanks!
Comment #254
davidneedhamThe patch in #249 applies cleanly
, but seems to fail on db updates.Update: This was my bad. I failed to run updates after updating redirect to the latest dev prior to applying this patch. Everything seems fine now and the db updates apply cleanly and appear to have resolved the issues.
Comment #255
stefan.r CreditAttribution: stefan.r commented@davidneedham might your issue have been due to this? #1662704: move RedirectController to a separate include file
Comment #256
stefan.r CreditAttribution: stefan.r commented@vinmassaro, I realize at this point several people are already running this patch so if the database changes, I'll endeavor to provide update hooks.
In any case the patch seems close enough to be committed at this stage.
Comment #257
jsenich CreditAttribution: jsenich commentedPatch #249 works for me. Big thanks to everybody that worked on it!
Comment #258
weri CreditAttribution: weri commentedWe had the problem with circular redirects on multiple sites. The Patch #249 fixes the problem and seems to work properly on all sites.
Comment #259
candelas CreditAttribution: candelas commentedPatch in #249 works well for a multilingual site. Thanks a lot. I hope this goes to dev :)
Comment #260
askibinski CreditAttribution: askibinski commentedSame here, applied #249 to several sites without any problems.
Comment #261
mrmikedewolf CreditAttribution: mrmikedewolf commentedI prefer the patch in #146. In my opinion #249 makes too many changes to the structure of the module. #146 is simple, concise, and solves the problem without reengineering. The firm that I work with has been using this patch on enterprise drupal websites for over a year and have never had a problem. Many thanks to SylvainM.
I've renamed it to follow drupal conventions. If this is committed, please credit the original author.
Comment #263
stefan.r CreditAttribution: stefan.r commented@mrmikedewolf: there was some discussion about that earlier and the module maintainer (Dave Reid) did not want to take the approach in #146, as such there is very little chance of that ever getting committed. Refer to comments #193, #195, #199, #204 for reference.
Comment #264
stefan.r CreditAttribution: stefan.r commentedComment #265
Anonymous (not verified) CreditAttribution: Anonymous commentedComment #266
peterx CreditAttribution: peterx commentedWorks on my site as described on the box. Given the age of the RC2, this change should be committed then cut to RC3. The module page will need a reminder to run update.php.
Comment #267
candelas CreditAttribution: candelas commentedI think it is very important to commit this patch, since there are other patches like https://www.drupal.org/node/905914 that will have to be modified. Thanks a lot for your excellent work :)
Comment #268
candelas CreditAttribution: candelas commentedAlso I have been using it in a multilingual site for 13 days, renaming nodes and no circular redirects have shown.
Comment #269
vadym.kononenko CreditAttribution: vadym.kononenko commentedPatch updated to current -dev.
Comment #271
stefan.r CreditAttribution: stefan.r commented#249 is already against current dev, there is no need to re-roll
Comment #273
candelas CreditAttribution: candelas commentedI change the status that was changed by #270 after the failure.
Comment #274
Charles BelovI'm concerned about "Includes a hook_update_N() to remove any existing redirects." in the proposed solution, at least the proposed solution that is in the summary at the top of this issue.
(Edit: Removed steps involving Workbench Moderation from this issue, moved them to #2395917: Redirection and alias created with same alias/node pair when renaming draft node per @stefan.r in #278 and related that issue to this one, so as not to cause confusion in this current issue.)
Comment #275
stefan.r CreditAttribution: stefan.r commented@Charles Belov does the patch in #249 address this concern? That update hook disables redirects, it doesn't delete them.
Comment #276
Charles BelovStephen - If #249 disables redirects, then it sounds like it doesn't do what I want.
The following is a description of what I would be seeking, without reference to #249.
I want to keep all but one of the redirects and have them be still active. What I don't want is something to have the same entry in both the redirect table and the alias table; such an entry belongs in the alias table only. The circular redirect appears to me to be the fault of the newest page alias being present in both the redirect table and the alias table.
(Edit: Removed lengthy description involving Workbench Moderation from this issue, moved them to #2395917: Redirection and alias created with same alias/node pair when renaming draft node per @stefan.r in #278 and related that issue to this one, so as not to cause confusion in this current issue.)
If I have misunderstood the original issue and my steps in #274 are actually a separate, but related, issue, then I apologize for inadvertently hijacking this thread. Please let me know and I'll be happy to create a new issue and relate it to this issue.
If I have misunderstood what #249 is disabling and it's actually doing one of the above two options, please clarify and I'll be happy to try it. As described it sounds like it's not doing what I'm trying to accomplish.
Comment #277
alfaguru CreditAttribution: alfaguru commented@Charles, yes, I have just come here having previously applied patch #249 yet seeing an infinite loop after reverting a file revision. This module should never permit a redirect to exist that matches the current alias for an entity. Unfortunately when making reversions this can happen, and I suspect it's quite hard to guard against, given the complexities involved.
Can I suggest that the old logic that displayed a message be resurrected? At the same time, if that event occurs the active redirect should be automatically disabled. Also, given that it may be seen by people who are not developers the message text should be made more appropriate for a general audience.
Comment #278
stefan.r CreditAttribution: stefan.r commented@Charles I may be wrong but that sounds like a separate issue (and @alfaguru's sounds like yet another one, perhaps hook_path_update() is not triggered during a reversion?)
Also as to the ""Oops, looks like this request tried to create an infinite loop. We do not allow such things here. We are a professional website!" message, that exists only in older versions of redirect and doesn't appear in the dev version anymore.
Comment #279
alfaguru CreditAttribution: alfaguru commented@stefan as regards the message, I know it no longer appears, but it's the logic associated with it that I think has some value. First, it stops the page breaking, which is surely a good thing, and offers the opportunity to do something about the underlying problem.
I don't know, because I haven't investigated, how the path is getting updated in this case and whether that hook is triggered. Ideally I would like this module to be more robust and less dependent on other modules doing the right thing. I got another infinite loop shortly after reporting this one, for a node this time, so it's not just file revisions (which are pretty bleeding edge so one expects some hiccups).
Comment #280
stefan.r CreditAttribution: stefan.r commentedCan you investigate how that node infinite loop happened, or give steps to recreate that issue?
You're the first one to report this issue and the patch in this issue has been having essentially the same behavior for over a year so your specific issue may not be due to the patch.
Comment #281
peterx CreditAttribution: peterx commentedA bad message is better than a white screen of death. Anything is better than leaving us with a dead screen. Given that the bad message would be seen mostly by internal staff, editors etc, it is better than the dead screen. I think we should put through a fix for the original dead screen problem then work on other cases.
Comment #282
rcodina CreditAttribution: rcodina commentedI just can't understand why this issue is taking so long to be fixed (2 years). There are a lot of users of this module experiencing this problem and most of them don't know about php/git and only mind modules to work correctly. The patch on #146 works like a charm. Why it hasn't been commited yet? I know you want to keep old links that produces the loops but what is more important here is to fix the issue ASAP so users don't get pissed off.
Comment #283
stefan.r CreditAttribution: stefan.r commented@peterx if you want back the old message, you can apply a reverse patch of the patch posted in #57 over at #1263832: Remove session-based flood / loop detection since it performs poorly, and has unfixable race conditions. Keep in mind there are issues with it (as mentioned in the other thread).
Just to confirm, you are running the dev version with patch #249 and have run all the update hooks?
As to why we aren't committing anything, or even any "quick-and-dirty" fixes which may introduce other issues such as mentioned in #281/#282, it's likely because the maintainer is busy -- last time he popped into this thread seeems to be September 24, 2014.
Comment #284
rcodina CreditAttribution: rcodina commented@stefan.r A lot of people told patch #146 was fine with no undesired side effects. In fact, I'm running it on several websites with no problems so far. If mantainer is busy maybe someone can ask to be co-mantainer. I think a critical issue like this cannot be open for 2 years (so far).
Comment #285
peterx CreditAttribution: peterx commented@stephan, I am not thinking of using the old message for the basic fix. I was thinking of using the basic fix for the most common case then put up messages for the edge cases while we develop fixes for them. Have a "quick and dirty" fall through message when all else fails. Given that loops end up as dead screen space with nothing to help the user, making something visible is preferable.
The loops can also silently kill cron and processes. Something, anything, in watchdog could be the first response to each new case.
Comment #286
fenstratThe issue summary really needs updating here. The approach of deleting the redirects was changed from #193 onwards based on feedback from @Dave Reid (#195 has a use case). Disabling the redirects is a sound alternative and the direction the module maintainer indicated. With an updated issue summary this is much more likely to get committed.
Comment #287
stefan.r CreditAttribution: stefan.r commentedComment #288
stefan.r CreditAttribution: stefan.r commentedComment #289
candelas CreditAttribution: candelas commented@stefan.r a new dev has been committed. I don't know if you will have to change something. In my site your patch is working grate.
Comment #291
stefan.r CreditAttribution: stefan.r commented@candelas looks like tests still pass
Comment #292
candelas CreditAttribution: candelas commented@stefan.r super. I hope it gets in dev since it is the last critical bug and many patches are pending and maybe need to be changed after this. Do you think that it can be set to patch to be ported?
Comment #293
chiebert CreditAttribution: chiebert commentedJust tested against latest -dev (2015-Jan-05), and while the patch in #249 applied cleanly, I now get a PDOException:
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'status' in 'where clause': SELECT redirect.rid AS rid FROM {redirect} redirect WHERE (status = :db_condition_placeholder_0) AND( (source LIKE :db_condition_placeholder_1 ESCAPE '\\') OR (source = :db_condition_placeholder_2) )AND (language IN (:db_condition_placeholder_3, :db_condition_placeholder_4)) ; Array ( [:db_condition_placeholder_0] => 1 [:db_condition_placeholder_1] => landing [:db_condition_placeholder_2] => [:db_condition_placeholder_3] => en [:db_condition_placeholder_4] => und ) in redirect_load_by_source() (line 580 of /Users/my-user/Sites/mysite/sites/all/modules/redirect/redirect.module).
Running on local MAMP environment, PHP 5.3.29, drupal 7.34, redirect-7.x-1.x-dev (2015-Jan-05) patched only with #249
Comment #294
vinmassaro CreditAttribution: vinmassaro commented@chiebert: Did you apply database updates?
Comment #295
chiebert CreditAttribution: chiebert commented@vinmassaro Clearly not. Lesson learned. Patch #249 applies cleanly against redirect-7.x-1.x dev (2015-Jan-05), and works as designed once the lame user runs
drush updb
...Excuse me while I go get another coffee...
Comment #296
rwilson0429 CreditAttribution: rwilson0429 commentedI can't get #249 to apply cleanly. When I try to apply the patch I get the following messages. I tried to patch on both my local Windows7 machine and on my staging Linux host system. Any help on what I'm doing wrong is much appreciated.
Comment #297
stefan.r CreditAttribution: stefan.r commentedre-roll of #249 -- looks like a commit from yesterday finally stopped the patch from applying :)
IMPORTANT: remember to run database updates after applying this patch!
Comment #298
stefan.r CreditAttribution: stefan.r commentedComment #299
stefan.r CreditAttribution: stefan.r commentedSetting back to RTBC
Comment #300
candelas CreditAttribution: candelas commented@stefan.r looks like Dave Reid is reviewing the issue and committing. I hope he decides to commit this one and other bugs can be checked from this and you don't have to adapt the patch... :)
Comment #301
alfaguru CreditAttribution: alfaguru commentedFurther to my comment above I found that the code I was using had not got the latest patch after all. Have applied it now and all seems good so far. Apologies for any confusion.
Comment #302
jackalope CreditAttribution: jackalope commentedThe patch in #297 kills my D7 site when I apply it to the most recent dev release, causing a "The website encountered an unexpected error. Please try again later." message to display on the site.
After reverting the patch I can access the site again and see this error in the database log:
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'status' in 'where clause': SELECT redirect.rid AS rid FROM {redirect} redirect WHERE (status = :db_condition_placeholder_0) AND (source LIKE :db_condition_placeholder_1 ESCAPE '\\') AND (language IN (:db_condition_placeholder_2, :db_condition_placeholder_3)) ; Array ( [:db_condition_placeholder_0] => 1 [:db_condition_placeholder_1] => in-the-news/29588/194 195 206 239 [:db_condition_placeholder_2] => en [:db_condition_placeholder_3] => und ) in redirect_load_by_source() (line 584 of /var/www/sitename/public_html/sites/all/modules/redirect/redirect.module).
Trying to apply older patches causes the same problem, so I've just reverted to an earlier (patched) dev version of redirect for now.
Comment #303
vinmassaro CreditAttribution: vinmassaro commented@jackalope: Did you apply database updates? See comment #295, fixed after applying database updates.
Comment #304
jackalope CreditAttribution: jackalope commented@vinmassaro - I did apply database updates, but unfortunately the site remained broken with that error message until I reverted the update & patch.
Comment #305
stefan.r CreditAttribution: stefan.r commented@jacklope running the update hooks should fix the problem you are having. Update hook number 7101 adds the status column to the redirect table, and it is impossible for that error to appear when the column already exists. So if it's not being added, something obvious is being overlooked on your setup... Some suggestions:
a) You'd need to first apply the patch and then run database updates (drush updatedb or going to update.php). The 7101 update hook should be listed among updates to apply -- this is the update hook that adds the "schema" field. If this is not the case, then:
b) Make sure that the redirect files you have patched are the ones drupal is actually using (check by doing
SELECT filename FROM system WHERE name = 'redirect';
). Check that that file has actually been patched, and whether you didn't accidently patch another one.c) Double check that schema_version = 7100 before running update hooks when doing
SELECT schema_version FROM system WHERE name = 'redirect';
Comment #306
stefan.r CreditAttribution: stefan.r commentedI just double checked that update hooks still run correctly with the latest dev release and patch. This still seems to be the case.
Before updates, the correct updates appear in update.php:
After updates, the status column is created correctly on the redirect table:
Comment #307
squarecandy CreditAttribution: squarecandy commentedI was able to apply the patch successfully and it is working as expected so far.
However, I did need to run
drush updatedb
twice to get it to work. Not sure if there's a way to get the full database update to run in one go…that's beyond my skill set. But here's what my drush updatedb looked like.Comment #308
squarecandy CreditAttribution: squarecandy commentedjust to follow up - the patch is working for me and this is a pretty essential fix for this module. I would vote for adding it to the dev version ASAP even if the database update situation doesn't have an easy fix.
Comment #309
jackalope CreditAttribution: jackalope commented@stefan.r -- thanks for the tips. The key seems to be this:
For some reason, schema_version = 7101 before I run the new update hooks, rather than 7100. This has been the case on each of my Drupal 7 sites; I'm not sure why! But running
UPDATE system SET schema_version=7100 WHERE name = 'redirect';
fixes that and lets me use the newest patch.Comment #310
ChaseOnTheWeb@jackalope -- You didn't happen to be using one of the early patches from this thread, did you? Those early patches defined a 7101 update before the maintainer decided to go in a different direction, so the "official" 7101 in the newer patches isn't invoked.
Though that's a potential gotcha anytime you use a patch with an update hook, the need to fix the system table might be good to note in the release notes since quite a few people throughout this thread (and surely many lurkers) have been using the early patches.
Comment #311
jackalope CreditAttribution: jackalope commented@marleythedog -- yes, I've definitely used some of the early patches on the thread. Makes sense that that's the problem on all of the sites I maintain.
UPDATE system SET schema_version=7100 WHERE name = 'redirect';
is a fairly easy solution.Thanks so much for the help, everyone!
Comment #312
stefan.r CreditAttribution: stefan.r commented@squarecandy: the RedirectController issue is very unlikely to be related to this patch, as of 4 days ago it's in redirect.controller.inc (#1662704: move RedirectController to a separate include file) and this file is included in redirect.info. Could you cross-post your error message in that issue? The update hook there may need a cache clear.
Comment #313
stefan.r CreditAttribution: stefan.r commentedJust to summarize in case any maintainer reviews this issue: the patch in the current form has been RTBC since #249, for over 2 months (ie. November 5, 2014), and no issues have come up yet other than some support requests and a possible incompatibility reported by "Charles Belov" which we can't replicate.
Other than that, patch #249 has received positive reviews from the following users:
Comment #314
vegardjo CreditAttribution: vegardjo commentedI can also confirm that patch in #249 works for me.
Comment #315
Leeteq CreditAttribution: Leeteq commentedThanks for pointing out the status so clearly, @stefan.r , high time to get this into -dev.
It cannot be worse to leave -dev in its current state than committing this one.
Depending on other issues, perhaps enough to trigger a new "recommended" release, although in review of issues such as this one, "recommended" has long lost its meaning anyway.
Edit: I meant "recommended", not "stable". Corrected.
Comment #316
kylebrowning CreditAttribution: kylebrowning commentedPatch seems to fail against current dev.
Comment #317
vinmassaro CreditAttribution: vinmassaro commented@kylebrowning: patch in #297 applies cleanly to 7.x-1.x-dev for me:
Testbot is still green, last tested 01/06/15, a day after the last commit to 7.x-1.x-dev.
Comment #318
DamienMcKenna+1 for the patch in #297 applying correctly against the current 7.x-1.x-dev (I just tested it).
Comment #319
AnybodyThis is a really really imporant issue and I'm happy to confirm that the latest patch works great. Can we get this commited? :)
Comment #320
candelas CreditAttribution: candelas commentedI agree with @Anibyody, @stefan.r don't you think that it can be classified as Patch (to be ported)?
Comment #323
Anybody@Dave Reid: #297 should be the right one
Comment #325
stefan.r CreditAttribution: stefan.r commentedWoohoo! Tests are green! :)
Comment #326
Dave ReidSo the 'source_language' index was designed specifically for the redirect_load_by_source(). Should 'status' also be included in that index instead of it's own separate index?
Can be simplified just using $rids = db_query("SELECT r.rid FROM redirect r INNER JOIN url_alias u ON r.source = u.alias AND r.redirect = u.source AND r.language = u.language")->fetchCol() since that query is valid SQL-99.
This statement looks odd if it's not plural.
Should end in a period not a colon.
Should not be an extra line before the previous @param statement.
Not sure why this is really changed.
This seems to duplicate a lot of the query from redirect_load_by_source(). Seems like it might be useful to add a new redirect_fetch_rids_by_path() function which both this and redirect_load_by_source() would use.
This function seems really strange to me. I'd rather this loop through each redirect and manually set $redirect->status and call redirect_save(). Plus rather than needing two functions we could have just one: redirect_change_status_multiple(array $rids, $status);
Comment #327
DamienMcKennaThis patch addresses items 2, 3, 4 and 5 from Dave Reid's code review.
Comment #328
stefan.r CreditAttribution: stefan.r commentedInterdiff for reference. Changes look good to me.
Comment #329
stefan.r CreditAttribution: stefan.r commentedComment #331
stefan.r CreditAttribution: stefan.r commentedThis addresses items 1, 7 and 8.
As to why #6 was changed, with this patch it's not necessarily true that "the source path is already being redirected". A redirect with that source path exists, but it may be disabled (ie. not redirecting the source path).
Comment #332
stefan.r CreditAttribution: stefan.r commentedComment #333
stefan.r CreditAttribution: stefan.r commentedComment #334
Anybody#331 works for me. Further feedback please to get this live.
Comment #335
kylebrowning CreditAttribution: kylebrowning commentedDo we need to do anything if we applied #297 before applying #331?
Comment #336
stefan.r CreditAttribution: stefan.r commentedNope, we changed a mysql index, but for now that shouldn't matter.
I'll provide an upgrade path from #297 to the final patch as soon as this gets committed.
Comment #337
Nebel54I checked out patch #331, it looks very promising, but:
The function redirect_disable_multiple doesn't exist anymore, so the update_hook is broken when redirect loops exist.
Comment #338
stefan.r CreditAttribution: stefan.r commentedComment #339
rv0 CreditAttribution: rv0 commentedTried #338
Also had to run the update twice, class 'RedirectController' not found
Here's what happened:
Also, it did not solve circular redirect on my site(EDIT: fixed the issue, but browser had cached the redirect)Comment #340
stefan.r CreditAttribution: stefan.r commented@rv0, if you first run the updates, and then apply the patch (after) before running updates again, you'll see that the RedirectController issue is not caused by this patch. See #1662704: move RedirectController to a separate include file
It looks like that empty update hook (#7100) doesn't actually cause a registry rebuild?
Perhaps you can try drush registry-rebuild after downloading the latest dev, as with this fatal error, update hook #7102 never runs, so the circular redirect can't be fixed.
Comment #341
heddnre #340: update.php/ drush updb will only flush cache and rebuild the registry at the end of its processing. Since there are multiple update hooks for redirect, the earlier one won't rebuild the registry in time for the second.
Since this isn't the first report of the issue, I'm marking as needs work. The only option I can think of is to manually rebuild the registry in this hook_update. Unless you can think of another solution.
Comment #342
stefan.r CreditAttribution: stefan.r commented@heddn: as that RedirectController issue is unrelated to this patch/this issue, shouldn't that be in a separate drupal.org issue?
Indeed the solution seems to be as simple as putting a registry_rebuild() in an update hook. redirect_update_7100 seems like an obvious candidate :)
Comment #343
heddnre #342: It is only an issue because of the update hook in here. Normally, cache clear isn't needed between update hooks so adding an unnecessary registry rebuild seems unneeded. But since this patch's update does use something that requires a registry rebuild, I feel it is the place of this issue to resolve. Image that the hook_update in this issue never got committed (for some reason). Then the rebuild in redirect_update_7100 is entirely unneccessary.
Comment #344
stefan.r CreditAttribution: stefan.r commentedComment #345
stefan.r CreditAttribution: stefan.r commentedComment #346
rv0 CreditAttribution: rv0 commentedRE: @stefan.r
well, I did run "drush updatedb" twice, so update 7102 did successfully run after all.. So all is fine. (for some reason the relevant part got trimmed in my reply, I tried to edit but it got trimmed every time.. d.o. bug i guess..)
Anyhow, the need to run it twice was already reported in #307
Comment #347
Nebel54Just wanted to report back that the patch #338 did work fine in our setup, it detected and removed 40 circular redirects during the update.
Comment #348
stefan.r CreditAttribution: stefan.r commentedJust for reference, here's an interdiff between #297 (that was marked RTBC and revised after review by Dave Reid) and the current patch (#345).
To summarize, it includes fixes to the points pointed out by Dave Reid as well as a modified update hook #7000 in order to address the issue with the registry being outdated pointed out in #254, #307, #339, #341
It would be good if we could get some further reviews so we can get this back to RTBC!
Comment #349
stefan.r CreditAttribution: stefan.r commentedComment #350
nicholasruunu CreditAttribution: nicholasruunu commented#349,
Just updated to redirect --dev and patched with #345.
It seems to work great, in update.php I got the message that 5 redirects were removed.
I tried changing a url on a node (got redirect) and when changing back to the original url the redirect was disabled.
Only problem is that I have no way of checking which redirects that was removed.
It is a bit scary not being able to check affected nodes so it would be nice to at least display them in the update message if possible.
Comment #351
nicholasruunu CreditAttribution: nicholasruunu commentedHm, I went back and checked this, got the 5 rids from $rids_to_disable, checked them all and they had status 1.
After the update when they're supposed to be disabled, all 5 still have status 1.
Can someone else reproduce this, or is it a problem with my db?
Update:
Problem seems to be redirect_change_status_multiple doesn't load the redirects with any status.
That leads to $redirect->original->status not existing and never goes into this:
redirect_save function L:799
Update:
Seems like the schema cache might be the problem.
drupal_get_schema('redirect') in this process doesn't return status in fields so it won't be updated.
common.inc:7111
Comment #352
nicholasruunu CreditAttribution: nicholasruunu commentedI have fixed the cache problem by running cache_clear_all('schema', 'cache') after the new fields are added to the db.
I've also added which routes that gets disabled so you have a chance to make sure they work, here's an example:
http://cl.ly/image/1S2C2V2R3B29
Comment #354
stefan.r CreditAttribution: stefan.r commentedre-roll of @nicholasruunu's patch.
Good find on the caching issue and the new message is great. Changes look good!
Comment #355
nicholasruunu CreditAttribution: nicholasruunu commented#354, Thanks for rerolling. This works for me, reverted db and code and applied the latest patch.
One issue might be that updating the module without running update.php will give fatal error pretty much everywhere.
Is this something that could/should be fixed? I'm happy with this though.
Comment #356
Alan D. CreditAttribution: Alan D. commentedOnly if it blocks the site from running update.php / drush update db
Comment #357
stefan.r CreditAttribution: stefan.r commentedThe fatal error is about the class RedirectController not being found due to a file being renamed, correct?
I think you can still run update.php when that is the case, so we should be able to live with this.
Comment #358
stefan.r CreditAttribution: stefan.r commentedComment #359
stefan.r CreditAttribution: stefan.r commentedComment #360
nicholasruunu CreditAttribution: nicholasruunu commented@stefan.r, My fatal error was trying to fetch redirect.status from the db, but update.php works, not sure about drush updatedb.
Comment #361
rv0 CreditAttribution: rv0 commentedTested #354 on another site, no issues at all, applies cleanly and seems to fix the issues.
Comment #362
hass CreditAttribution: hass commented"Save" strings in tests need to be t'ified.
Comment #363
nicholasruunu CreditAttribution: nicholasruunu commented@hass, can you elaborate? I don't quite understand.
Comment #364
stefan.r CreditAttribution: stefan.r commentedComment #365
jackalope CreditAttribution: jackalope commentedJust tried the patch in #364 against redirect-7.x-1.x-dev, and the changes to redirect.test fail!
Comment #367
stefan.r CreditAttribution: stefan.r commentedComment #368
hass CreditAttribution: hass commentedGreat. In what century is this case getting fixed? ~2 years are really crazy if basic functionality of this module makes it completely broken and requires a downgrade. No idea why so many people have rc1 installed.
Comment #369
Charles Belov@nicholasruunu #363 t'ified = All text strings need to be wrapped in the t() function to make them translatable.
Comment #370
stefan.r CreditAttribution: stefan.r commented@hass can this go back to RTBC?
Comment #371
candelas CreditAttribution: candelas commented@stefanr thanks for all your work. It would be good if you use t() on the few lines that they haven't. Good work :)
Comment #372
stefan.r CreditAttribution: stefan.r commented@candelas which lines are that? Aren't all the "Save" strings wrapped in t() in #367?
Comment #373
candelas CreditAttribution: candelas commentedFrom your patch. Maybe I am wrong... :) I mark with
//NEEDS T()
I hope it helps :)+/**
* Act on a redirect being redirected.
*
* This hook is invoked from redirect_redirect() before the redirect callback
diff --git a/redirect.install b/redirect.install
index 6ccb75b..2b2a7d3 100644
--- a/redirect.install
+++ b/redirect.install
@@ -86,7 +86,14 @@ function redirect_schema() {
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
- 'description' => 'The timestamp of when the redirect was last accessed.'
+ 'description' => 'The timestamp of when the redirect was last accessed.',
//NEEDS T()
+ ),
+ 'status' => array(
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ 'default' => 1,
+ 'description' => 'Boolean indicating whether the redirect is enabled (visible to non-administrators).',
//NEEDS T()
),
),
'primary key' => array('rid'),
----------------------------------------------------------
@@ -363,3 +376,71 @@ function _redirect_migrate_path_redirect_variables() {
variable_del($old_variable);
}
}
+
+/**
+ * Add status field to redirect table.
+ */
+function redirect_update_7101() {
+ $field = array(
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => TRUE,
+ 'default' => 1,
+ 'description' => 'Boolean indicating whether the redirect is enabled (visible to non-administrators).',
//NEEDS T()
+ );
+ db_add_field('redirect', 'status', $field);
+ db_drop_index('redirect', 'source_language');
+ db_add_index('redirect', 'status_source_language', array(
+ 'status',
+ 'source',
+ 'language',
+ ));
-----------------------------------------------------------
diff --git a/redirect.test b/redirect.test
index 1c237f8..33c6d23 100644
--- a/redirect.test
+++ b/redirect.test
@@ -229,16 +229,59 @@ class RedirectFunctionalTest extends RedirectTestHelper {
$node = $this->drupalCreateNode(array('type' => 'article', 'path' => array('alias' => 'first-alias')));
// Change the node's alias will create an automatic redirect from 'first-alias' to the node.
- $this->drupalPost("node/{$node->nid}/edit", array('path[alias]' => 'second-alias'), 'Save');
- //$redirect = redirect_load_by_source('first-alias');
- //$this->assertRedirect($redirect);
+ $this->drupalPost("node/{$node->nid}/edit", array('path[alias]' => 'second-alias'), t('Save'));
+ $this->drupalGet('first-alias');
+ $this->assertText($node->title);
+
+ $this->drupalPost("node/{$node->nid}/edit", array('path[alias]' => 'first-alias'), t('Save'));
+ $this->assertResponse(200, "Changing node's alias back to 'first-alias' does not break page load with a circular redirect.");
//NEEDS T()
+ $this->assertNoText('Infinite redirect loop prevented.');
//NEEDS T()
+ $this->drupalGet('second-alias');
+ $this->assertText($node->title);
+
+ $this->drupalPost("node/{$node->nid}/edit", array('path[alias]' => 'second-alias'), t('Save'));
+ $this->assertResponse(200, "Changing node's alias back to 'second-alias' does not break page load with a circular redirect.");
//NEEDS T()
+ $this->assertNoText('Infinite redirect loop prevented.');
+ // Check that first-alias redirect has been re-enabled.
+ $this->drupalGet('first-alias');
+ $this->assertText($node->title);
+ }
+
+ function testPathAddOverwriteRedirects() {
+ // Create an initial article node with a path alias.
+ $first_node = $this->drupalCreateNode(array('type' => 'article', 'path' => array('alias' => 'first-alias')));
+ // Change the node's alias will create an automatic redirect from 'first-alias' to the node.
+ $this->drupalPost("node/{$first_node->nid}/edit", array('path[alias]' => 'second-alias'), t('Save'));
+
+ // Now create a second article node with the same alias as the redirect
+ // created above.
+ $second_node = $this->drupalCreateNode(array('type' => 'article', 'path' => array('alias' => 'first-alias')));
- $this->drupalPost("node/{$node->nid}/edit", array('path[alias]' => 'first-alias'), 'Save');
- //$redirect = redirect_load_by_source('second-alias');
- //$this->assertRedirect($redirect);
+ // Visit the path 'first-alias' which should be an alias for $second_node.
+ $this->drupalGet('first-alias');
+ $this->assertNoText($first_node->title, 'Adding a new path alias that matches an existing redirect disables the redirect.');
//NEEDS T()
+ $this->assertText($second_node->title, 'Adding a new path alias that matches an existing redirect disables the redirect.');
//NEEDS T()
+ }
- $this->drupalPost("node/{$node->nid}/edit", array('path[alias]' => 'second-alias'), 'Save');
- //$redirect = redirect_load_by_source('first-alias');
- //$this->assertRedirect($redirect);
+ function testDisableEnableRedirect() {
+ // Add a new redirect.
+ $redirect = $this->addRedirect('redirect', 'node');
+ // Check that it is enabled.
+ $this->assertEqual($redirect->status, 1);
+
+ // Disable the redirect.
+ $edit = array('status' => FALSE);
+ $this->drupalPost("admin/config/search/redirect/edit/{$redirect->rid}", $edit, t('Save'));
+ $redirect = redirect_load($redirect->rid);
+ // Check that it has been disabled.
+ $this->assertEqual($redirect->status, 0);
+ $this->drupalGet("admin/config/search/redirect/edit/{$redirect->rid}");
+ $this->assertNoFieldChecked('edit-status', 'status is unchecked');
//NEEDS T()
+ $this->assertNoRedirect($redirect);
+
+ // Re-enable the redirect.
+ $edit = array('status' => 1);
+ $this->drupalPost("admin/config/search/redirect/edit/{$redirect->rid}", $edit, t('Save'));
+ $this->assertRedirect($redirect);
}
}
Comment #374
BerdirNone of those need t(), schema descriptions and assertion messages are not translated.
Comment #375
candelas CreditAttribution: candelas commentedThanks @Berdir. So much to learn in Drupal :)
I hope this patch gets in dev. It is really needed.
Comment #376
hass CreditAttribution: hass commented@Bedir:
t('Save')
is correct. This is not an assertion message. Without t() it is not correct. In case you are on a translated page the test will not be able to find and press the save button. Database schema will not be translated like assertion messages.The last patch was correct change. Nothing else need to be changed.
Comment #377
hass CreditAttribution: hass commented#373: None of these require t().
Comment #378
nicholasruunu CreditAttribution: nicholasruunu commentedI noticed that from my patch you can get duplicate rids back so some links will come out twice.
If someone wants to group the query in redirect_update_7102 on rids that would be great, otherwise I'll try to fix it when I can.
Comment #379
stefan.r CreditAttribution: stefan.r commented@nicholasruunu, as
rid
is the primary key and the query isSELECT r.rid, r.source, r.redirect FROM redirect r INNER JOIN url_alias u ON r.source = u.alias AND r.redirect = u.source AND r.language = u.language
, how is it even possible to get duplicate results from there?Comment #380
nicholasruunu CreditAttribution: nicholasruunu commented@stefan.r,
You'd think it wouldn't, but still:
http://cl.ly/image/0H371I321q1F
Fixed:
http://cl.ly/image/0Z461k093n16
Update:
We should probably at the same time surround tables with {} for table prefix compatibility.
Update:
It happens when url_alias have two entries with the same source/alias:
http://cl.ly/image/2O2C2Z432N2L
Comment #381
stefan.r CreditAttribution: stefan.r commentedComment #382
nicholasruunu CreditAttribution: nicholasruunu commented@stefan.r,
Good job, works as expected.
Comment #383
PQ CreditAttribution: PQ commentedJust wanted to show some appreciation for @stefan.r and everyone else on this thread who's been working on this for so long. Thanks for putting so much time and patience in working towards fixing this issue.
Comment #384
hass CreditAttribution: hass commentedNot only that this translatable strings are not correct, this can run into serious troubles. You may run into a timeout or megabytes of webpage inside the batch. This makes the batch page failing. I strongly suggest to change this into watchdog message(s).
Comment #385
stefan.r CreditAttribution: stefan.r commented@hass what's incorrect about the strings? I'm also reluctant to take out the displayed message, I quite like it, and for a timeout or for "megabytes" to happen we'd need the Drupal install to have thousands and thousands of circular redirects. Maybe I'm wrong but isn't that an extreme edge case?
A watchdog message upon disabling/enabling may be useful in any case, perhaps that should be happening every time a redirect gets disabled/enabled, and not just in the update batch?
Comment #386
hass CreditAttribution: hass commented'1 circular redirect causing infinite loop was disabled: !disabled_redirects_list'
This is correct.
There are sites that are large scale. Outputting 10.000 found redirect loops in a list sounds not unrealistic to me and this may bring the batch down. I think an update should be design wise reliable. We should use watchdog for logging and just tell the user there have been xxx redirect loops found and these deleted ones can be found in watchdog. Do not output sooo much data on one page, please. That is very risky.
Comment #387
nicholasruunu CreditAttribution: nicholasruunu commented@hass, That's a really small operation, can't really see how that would be a problem.
I don't really know why watchdog would help with this either.
Did you have any problems with the batch job failing?
Because I had to enable redirect on one site since a function from redirect.module is being used.
And isn't this operation being run in a batch job and thus timeout shouldn't be a problem anyway?
Update:
If the problem is with too much output, perhaps we can limit the output to say 200? It was really useful for me on a site with ~200 redirects.
Then we could put the rest on watchdog.
But what would happen if dblog is disabled?
Comment #388
stefan.r CreditAttribution: stefan.r commented@hass what specifically makes you concerned about a timeout?
Comment #389
stefan.r CreditAttribution: stefan.r commented(untested) implementation of @nicholaasruunu's suggestion
For those few sites with no logging at all and more than 200 circular loops, you'd expect them to have a test environment where they can enable logging and run updates before doing them on a live site.
If they lose that bit of information it's not a huge deal anyway. It's not that hard to find the recently disabled redirects if really needed.
Comment #391
nicholasruunu CreditAttribution: nicholasruunu commentedPerhaps just scrap the urls then, you could always just query for status = 0.
Since if you're running the migration you wouldn't have had status before anyway.
Comment #392
stefan.r CreditAttribution: stefan.r commentedOK, go ahead and take them out of my latest patch :)
Guessing there's a syntax error somewhere as well.
Comment #393
jwilson3In addition to syntax error (which i couldn't find reading the patch), a couple minor tweaks:
Should be something like
Should explain *why* the registry and edit info rebuild is actually needed, if not in the doc block comment, then at least an inline comment inside the functions curly braces.
Comment #394
rooby CreditAttribution: rooby commentedThe syntax error is here. No quote ending the message text.
Comment #395
stefan.r CreditAttribution: stefan.r commentedI've taken it out as requested by @nicholasruunu & @hass. It's logged in watchdog now.
Comment #397
stefan.r CreditAttribution: stefan.r commentedCommented update hook 7100 changes as per #393.
Comment #398
hass CreditAttribution: hass commentedBecause my database updates are incomplete? A failing update hooks are show stoppers.
No, a batch step itself can timeout. Only if you split the task into several rounds your are able to prevent a timeout. With 50.000 url aliases not unrealistic.
The update hook need to complete. If it fails users are lost. This is not an acceptable situation for an update hook.
Comment #399
vinmassaro CreditAttribution: vinmassaro commented@stefan.r: what is the procedure for testing the patch in #397 if we've already patched with #249? I'd like to give it a test to throw my hat in the ring to to move this forward, thanks!
Comment #400
nicholasruunu CreditAttribution: nicholasruunu commented@vinmassaro, if you have a database dump pre-update, download the development version of Redirect and apply the patch. Look over the interdiff since last reviewed patch. If it looks good, go through the update procedure again, and if successful, mark as reviewed and tested by the community. Thank you for being willing to participate!
Comment #401
jphelan CreditAttribution: jphelan commentedI've applied #397. It applied cleanly to 7.x-1.x-dev and all seems well. Ran updb via drush with no issues. I did a simple test changing the url and changing it back to the original and it disabled the first redirect as expected. I had NOT ever applied #249. Thanks for your work on this stefan.r.
Comment #402
travelvc CreditAttribution: travelvc commentedThank you @stefan.r and everyone for testing. Patch #249 worked for me. I'm now waiting for an official release.
Comment #403
ar-jan CreditAttribution: ar-jan commented@travelvc: then it would be better to test #397, because that's the latest patch, currently under review.
Comment #404
hanoii@nicholasruunu I second @vinmassaro question on what to do if you applied patch #249, what about when you don't have a pre-update dump of the db to re-apply cleanly?
Comment #405
heddnre #404: in your own custom module's hook_install add:
And in the future when applying a patch that isn't committed yet, move the patch's hook_install logic into your own custom module's hook_install. The reason you have to do this is because the previous run of hook_install has already updated Drupal's system table patch level.
Comment #406
hanoii@heddn, thanks, you could also edit the system table to run the update again, but what I am asking is if it's safe to just run the update_710x again or the changes done by the patch in #249 could conflict with the changes that should be done with the latest patch.
Comment #407
candelas CreditAttribution: candelas commented@heddn thanks I didn't know. Do I have to do that with #146 and #249 patches that I have in two sites? I will investigate that as soon this is in dev, now I am solving other problems.
(@stefan.r 4 more people saying that the patch works and we change status to reviewed and tested by the comunity, don't we?)
Almost there! (it is the longest issue that I met in Drupal)
Comment #408
Alan D. CreditAttribution: Alan D. commentedProbably needs the maintainers feedback, but I think that this is still flagged as needs work by:
So redirect_update_7102(&$sandbox) needs to be batched to avoid this issue.
Completely untested starter for someone:
Double check the rewritten queries produce the same result, and set $limit really low for testing, like 2 or 3, etc.
Comment #409
cmseasy CreditAttribution: cmseasy commented@Alan D
I'm not sure but, maybe VBO https://www.drupal.org/project/views_bulk_operations can solve your issue.
I think #408 is a new feature request.
Is it not better to create a new issue for #408, so this issue 'Fix and prevent circular redirects' can close and the solution commited?
Comment #410
nicholasruunu CreditAttribution: nicholasruunu commentedI am getting really angry now, so please excuse my ignorance and directness.
This module is from 2003 and is still a work in progress as a Drupal 7 module working with global redirect and whatever.
This issue is over 2 years old. This module is called redirect and is a valuable module for all of us.
People have asked for maintainer feedback, this thread is again over 2 years old. It's irresponsible to the Drupal community and most to all of us trying to bring this patch forward.
The ONLY reason this is not part of our build package is this bug. We've spent hundreds of dollars of customer money to try and get this fixed. WHICH IT ALREADY IS. It's just about semantics and edge cases at this point.
This is the actual time for a fork, if @stephanr, who's made a lot of great progress, or anyone else is up for it. I'll be in to help spending my free time on this. Drop me an inbox message.
I can't stress enough how disappointed I am, if you can't handle a project, please do the right thing and hand it over.
Comment #411
stefan.r CreditAttribution: stefan.r commentedTo be fair, the maintainer has been chiming in with feedback every couple of weeks :)
The issue mentioned by @hass was more about the output than the actual queries. They are unexpensive so even with 10000 actual circular redirects (which I still don't see how anyone even on the largest scale sites would have that many), this shouldnt time out, should it?
Comment #412
rwilson0429 CreditAttribution: rwilson0429 commentedThanks stefan.r for calming the waters. You've done a fabulous job on this issue. Thank you and everyone else who is working us through this issue. Excuse me for getting off the real issue here, 'Fix and Prevent Circular Redirects' but, I am driven to say that the maintainer of this module is a huge and consistent contributor to the Drupal community for over 8 years (I believe). That's top-notch in my book. Thanks maintainer. I appreciate his hard work and efforts on this module and the many others that he maintains and gives freely to the community.
Comment #413
Alan D. CreditAttribution: Alan D. commentedWe maintain a few sites that do have content in the millions, but imho, we would never have an issue ourselves with the update script. (99.98% of this content is automated from feeds etc that would never have multiple aliases.)
Comment #414
travelvc CreditAttribution: travelvc commentedI am tracking this thread daily hoping for for an "official" update. I have tested the latest patches and they work fine for me and solve the redirect loop bug I am experiencing.
As a suggestion - since the development release is already better than the production release, why don't we set a date (for example, March 1) for everyone here to test and verify the latest patch, and commit to a release date. This can't drag on forever.
Comment #415
DamienMcKennaAll of Dave Reid's feedback has been resolved, there are no further items indicating problems with the patch, so I'm setting this to RTBC.
Comment #416
mxwright CreditAttribution: mxwright commentedPatch in #397 works for me too, though I still have to use it in conjunction with #1198028-13: Redirects do not work if $_SERVER['SCRIPT_NAME'] does not follow base_path
Edit: Second patch due to Drupal being in a sub directory on my server.
Comment #417
azinck CreditAttribution: azinck commentedI'm very sad to move this back to "needs work". #397 calls redirect_change_status_multiple() which calls redirect_save() which calls drupal_write_record() which, according to the docs, isn't allowed to be called via an update hook due to the potential for an unreliable schema cache. Practically speaking, in my testing my redirects get correctly disabled when running the update hooks via update.php but they don't get disabled (the update hook is run, and the correct # of items are indicated as being disabled by the text returned, but the status does not actually get correctly set) when called via drush updb. This is due to a stale schema cache.
We could switch to calling db_update directly, but then none of the proper redirect-related hooks like hook_redirect_update would get called. Instead, I'd suggest queuing the redirects that need to be changed and processing the queue during cron (hook_cron_queue_info) so that we can call redirect_save() in a "safe" environment.
Comment #418
azinck CreditAttribution: azinck commentedIn thinking about this a bit more I actually think we should go ahead and use db_update() here. I don't think it's important to invoke the redirect-related hooks as we're populating the value of the status field for the very first time.
Since we're no longer calling redirect_save() or drupal_write_record(), we no longer need the registry_rebuild() or entity cache clear or even to clear the schema cache so I've simplified the update hooks back down to a single hook.
Comment #419
azinck CreditAttribution: azinck commentedForgot to attach the interdiff. This is the diff between #397 and #418.
Comment #420
stefan.r CreditAttribution: stefan.r commentedThe code itself looks good, just wondering what "conflicting" means in "circular or conflicting redirect"? Perhaps we could clarify that wording?
+ * Add status field to redirect table. Mark circular or conflicting redirects as disabled.
Needs to be under 80 characters. How about:
* Add status field and mark circular or conflicting redirects as disabled.
Comment #421
azinck CreditAttribution: azinck commentedAh, oops! I didn't mean to leave in those changes to the comments. Those are leftover from some changes I was considering to disable redirects that match url aliases but that goes beyond the scope of this issue. I can reroll the patch when I get home.
Comment #422
azinck CreditAttribution: azinck commentedFixed the comments. Interdiff is with 418.
Comment #423
stefan.r CreditAttribution: stefan.r commentedThanks, patch looks ready again.
Comment #424
stefan.r CreditAttribution: stefan.r commentedComment #425
cmseasy CreditAttribution: cmseasy commentedHi
@azinck @stefan.r
Thanks for the fast patch on the latest issue (#417). Testing it now, looks ok at first sight.
@all followers
You are one of the 219 followers, I think a few are disappointed at the duration this isue exists, I am. But I know I dont't have the skills to help with the code and maybe a lot of you don't have php coder skills either. The coders / maintainers do a great job. And I am sure that they want to commit the solution of this issue as fast as possible. I do.
So, become an active follower: test the patch and give your feedback. It can give a boost to the next release of redirect. I am sure: you want that, together with 218 other followers!
Comment #426
cmseasy CreditAttribution: cmseasy commentedPatch #422 broke one of my sites compleet (white screen on all pages) and on other sites only the edit page of redirect was a white screen: and in the logs:
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'status' in 'where clause': SELECT redirect.rid AS rid FROM {redirect} redirect WHERE (status = :db_condition_placeholder_0) AND( (source LIKE :db_condition_placeholder_1 ESCAPE '\\') OR (source = :db_condition_placeholder_2) )AND (language IN (:db_condition_placeholder_3, :db_condition_placeholder_4)) ; Array ( [:db_condition_placeholder_0] => 1 [:db_condition_placeholder_1] => frontpage [:db_condition_placeholder_2] => [:db_condition_placeholder_3] => nl [:db_condition_placeholder_4] => und ) in redirect_fetch_rids_by_path() (regel 575 van /home/public_html/drupal-7/sites/all/modules/redirect/redirect.module).
The answer was in the database: the column 'status' was missing, update.php didn't help. Only re-install solved it, loosing the 'old' redirect rules. That is not wat we want on a live site.
The schema version of redirect for both, the updated version and the re-installed version, is 7100. My (live) sites with the old (not updated) redirect have schema version 7000.
Function redirect_update_7100() in redirect.install does nothing. Maybe missing a "create column 'status' " if not present in redirect.install?
Comment #427
nicholasruunu CreditAttribution: nicholasruunu commented@cmseasy, I'm guessing it's because #419 removed my cache_clear_all('schema', 'cache', TRUE);
I would expect update.php to clear all the cache itself after the batch, but it probably doesn't.
Is the problem fixed when clearing the cache?
Is this something we should do in the migration to prevent this or is the user expected to clear cache after db update?
Comment #428
cmseasy CreditAttribution: cmseasy commentedI didn't know that clearing caches can create columns in the database :-)
The problem is that column 'status' does not exist in the database and update.php did not create this column because creating this column is not part of the redirect.install script. So the problem is not fixed with a cache clear.
Look at the redirect.install of redirect 7.x-1.0-rc1: there is no 'status' column created (both: hook_schema or redirect_update). The redirect.install in Redirect dev+patch#422 creates the status column with hook_schema not in an redirect_update. There are 12 columns created in 7.x-1.0-rc1, there are 13 columns in the patched version.
As far as I know, cache clear is defined in the update module and a proces of update.php (line 882?).
Comment #429
DamienMcKenna@cmseasy: When you first applied the patch did update 7100 run?
Comment #430
cmseasy CreditAttribution: cmseasy commentedYes, and it worked: the schema version of redirect changed from 7000 to 7100 in the database 'system' row-table.
sorry there is.There is no "add column status" script in function redirect_update_7100() (see redirect.install), so it does nothing with this column.
Comment #431
stefan.r CreditAttribution: stefan.r commented@cmseasy you may want to do some further debugging, if redirect_update_7100() runs it should definitely create a "status" field on the redirect table...
Comment #432
azinck CreditAttribution: azinck commentedcmseasy: I'm confused by you saying that the "Function redirect_update_7100() in redirect.install does nothing." Patch 422 does add the necessary column in that update hook. This is what it looks like after the patch:
The part that makes this potentially tricky, and what I expect tripped you up, is that the dev version of this module does, in fact, define redirect_update_7100(). So if you install the dev version of this module and run update.php with that version before you patch with #422 then the redirect_update_7100() will never get called again and your database column won't get added.
Some tips for other folks looking to help test this:
And yes, the schema cache is definitely cleared by update.php and updb when they're finished running. That explicit call was only needed before because drupal_write_record was being called to write to the status column in the same update script call as was creating the column. Since we're now using db_update we're no longer relying on the schema cache.
Comment #433
DamienMcKenna@azinck: You should never repurpose an existing update script, you should always create a new one.
This new patch puts update_7100 back to the blank state it was previously, and moves the custom functionality into update_7101.
Comment #434
hass CreditAttribution: hass commentedWe typically do not need to support DEV to DEV upgrades. As RC1 had no update 7100 we can change this function until next release.
Comment #435
azinck CreditAttribution: azinck commentedYes, exactly, what hass said. 7100 only existed in the dev version.
Comment #436
azinck CreditAttribution: azinck commentedBut maybe we need to make an exception here based on the sheer amount of time since a release of redirect and the likely relatively high percentage of folks using the dev version.
Comment #437
stefan.r CreditAttribution: stefan.r commentedWell we can change 7100 but we must not necessarily. Maybe we can leave it up to the maintainer and stick to #433 for now as doing otherwise may trip up other reviewers?
Comment #438
hass CreditAttribution: hass commentedWe could also switch to 7101 and remove 7100 as it is empty and does nothing. This way we support DEV to DEV upgrades what is good to do, but not a must.
Comment #439
stefan.r CreditAttribution: stefan.r commentedOK let's do that. This patch removes update hook #7100.
Comment #440
DamienMcKenna@hass / @stefan.r: Yeah, that works too :)
Comment #441
cmseasy CreditAttribution: cmseasy commentedThanks for the discussion and the result of that, I will test patch #439 updating against 7000 (alpha) and 7100 (dev).
Comment #442
cmseasy CreditAttribution: cmseasy commentedUpdate against 7100 (patch422):
Comment #443
stefan.r CreditAttribution: stefan.r commented@cmeasy yes, that's to be expected. You can't run this patch against a previous patch...
Comment #444
heddnHere's an interdiff between the last RTBC (#397) and #439. Two small nits, not marking needs work, but good to pick up if we have to re-roll this again.
No need to duplicate code, call redirect_schema(), which will return the schema structure and use that as input to db_add_field().
The return from db_update is the count of records that are changed. Use it instead of calling count() on the $rids_to_disable array.
The $sandbox is now removed, this is OK since this is now using db_update and even on the slowest db installations, it should scale. This is ready for RTBC again.
Comment #445
hass CreditAttribution: hass commentedNo... *never* do this, please! If you change hook schema this will cause lots of troubles. Update hooks need to work in-depended or they may fail in future. Current patch is correct.
Comment #446
heddnIf hook schema changes in the future then repeating code is fine, in the future. Copy/paste into the hook_update at that point. But there isn't any need to repeat code, now. Coding for the future usually means additional complexity that is never utilized.
Regardless, now we are RTBC, let's get this thing committed!
Comment #447
azinck CreditAttribution: azinck commentedLooks good to me. The rename to redirect_update_7101 is smart to help folks already on dev. Let's get this in.
Comment #448
hass CreditAttribution: hass commentedNo, we write code once. It is absolutely correct to copy the field schema into the update function. If there comes hook 7201 and it changes the field again hook_schema will change and therefore 7101 will fail from this point. It is often missed that this happens. That is why project module 5.x and 6.x is seriously broken. You should make every update in-depended of every functions in the module or you run into troubles. Nobody will and like to test this upgrade paths in future properly. Do it once and do it right. Whenever possible do not depend on anything as it can and will change.
Comment #449
rooby CreditAttribution: rooby commented+1 for never directly calling the hook_schema() implementation from an update function.
Comment #450
cmseasy CreditAttribution: cmseasy commentedTest results redirect with patch #439
I bumped against an url_alias condition. On admin/config/search/path/settings the Update action must manual set to: "Create a new alias. Delete the old alias". Redirect does not work without this setting.
The comment under Update actions "What should Pathauto do when updating an existing content item which already has an alias? The Redirect module settings affect whether a redirect is created when an alias is deleted." is not clear abouth this condition and not documented (far as I know).
Possible solution: change the checkbox text on the URL redirect settings page admin/config/search/redirect/settings:
"Automatically create redirects when URL aliases are changed."
to, for example:
"Automatically create redirects when URL aliases are changed. Set Update actions in url aliases on: Create a new alias. Delete the old alias!"
------
Test url alias with the update action options:
Update actions in url aliases set to Do nothing:
No new alias is made, the old one exists.
No redirect made.
Result: ok.
Update actions in url aliases set to Create a new alias. Leave the existing alias functioning. :
A new alias is created, next to the old alias.
No redirect is made.
Result: ok.
Update actions in url aliases set to Create a new alias. Delete the old alias.
A new alias is made, removing the old alias
A redirect is made.
Result ok, see remark above.
------
Testing url alias and redirect:
1) First title (node made):
url alias is made.
no redirect.
Result: ok.
2) Change title (url change):
A new alias is made, removing the old alias from (1).
A redirect is made from old (first title) alias to node/#.
Result: ok.
3) Change title back to 'first title' (url change):
A new alias is made, equals the 'first title' alias (1).
A redirect is made from old 'çhanged title' alias made in (2) to node/#.
The 'first title' redirect made in (2) changed status to Disabled.
Result: ok.
During the test I never seen an error or warning message.
My compliments for the developers.
Comment #451
stefan.r CreditAttribution: stefan.r commented@cmseasy good to hear your tests were successful, thanks!
Comment #453
candelas CreditAttribution: candelas commented@stefan.r isn't enough tested now to ask @Dave Reid to check and commit or say what to be changed?
It would be great to be able to go for other bugs that are in the cue :) Thanks all for your work.
Comment #454
stefan.r CreditAttribution: stefan.r commentedYes, I think it is. Keep bugging him so we can get this in! :)
Comment #455
candelas CreditAttribution: candelas commented@Dave Reid, first thanks for the thousands of hours that you have gave to the community :)
Could you, please, check this critical issue to be able to commit it? Thanks
Comment #456
candelas CreditAttribution: candelas commented@stefan.r and all the other :)
I was thinking how to make more attractive to the module maintainer to check this issue. What do you think if we check that it works with all the other patches tested and review by the community? There are 9.
https://www.drupal.org/project/issues/redirect?text=&status=14&prioritie...
This is the only classified as critical, so I would think that is the one that would have preference, but if we check, there will be more efficient to commit in one moment all that work well.
Next week I have to implement this module in a site that I am building, so I have time to check.
Comment #457
flyke CreditAttribution: flyke commentedPatch #439 works for me.
Steps that were a prolem before:
- create and save a page with title 'Contact' (it auto generates alias '/contact')
- edit the page, change title to 'Contact us' (it auto generates alias '/contact-us' AND places a redirect from /contact to /contact-us)
- edit the page, change title to 'Contact' (it adds a redirect from /contact-us to /contact and thus infinite loop now)
With patch #439 -> problem solved.
Comment #458
travelvc CreditAttribution: travelvc commentedPatch #439 works for me! :)
Comment #459
1mundus CreditAttribution: 1mundus commentedIt seems that many people can confirm that the latest patch works. Please commit it, it's really critical for many of us. :)
Comment #460
cmseasy CreditAttribution: cmseasy commentedOn the main project page the maintainer Dave Reid is asking for a co-maintainer. I don't have the skills to maintain a module: who wants to help Dave committing this patch (maybe all 9 RVBC patches, see #457) to dev, rc# or even better to an official 7.x-1.0 release?
Comment #461
PQ CreditAttribution: PQ commentedJust a thought but would there be any merit in appealing to the Drupal association to fund the maintainer's time to get this in? I appreciate that the D.A. more or less commit in advance to what they are going to do with members's membership fees, but as a paying individual member myself, I would want to see funds spent to protect and maintain Drupal's reputation.
Whilst redirect is not part of core or indeed on a stable release, it is the 45th most used project in the ecosystem (https://www.drupal.org/project/usage) which means that a large proportion of all Drupal sites have it installed. In my experience if no pre-emptive action is taken more than half of site owners flag up issues with redirects relating directly to this issue. Site owners then consider this to be a bug either with Drupal or the individuals / organisation that put their site together, and their faith in Drupal as a whole and/or their vendor takes a knock.
This is why I personally feel that this is highly critical that this gets resolved ASAP. It's not an edge-case... as-is a large proportion of Drupal sites are exhibiting behaviour that's broken and highly visible and disruptive.
I also understand that the Dave Reid is stretched thin and is actively seeking co-maintainers to help. He does a fantastic job within the community and has contributed a huge amount. I appreciate that he has a finite amount of time he can put into these issues especially on an unpaid basis, but in the absence of any co-maintainer, there is effectively a bottle-neck here where no-one else can get this fix committed. This is why I'm suggesting that a small amount of our D.A. membership fees goes towards sponsoring getting this resolved once and for all, for the entire community's sake.
Thoughts?
Comment #462
candelas CreditAttribution: candelas commented@PQ I agree completely with your arguments and your proposal. Which steps are needed to make what you propose?
Comment #463
PQ CreditAttribution: PQ commented@candelas, Not entirely sure to be honest, I guess I'd like to see if anyone else on the thread would support this course of action or can provide a reason why it's not a good way forward. If feedback is positive then I could put together an open email to the DA, flagging up this discussion.
Comment #464
Charles Belov+1 for funding this issue. I don't feel comfortable implementing patches that have not been committed to at least dev, as it creates maintenance headaches.
Comment #465
ladybug_3777 CreditAttribution: ladybug_3777 commentedWOW, I just read through this thread and I can't believe how long this issue has gone on! I just installed this module for the first time today and immediately saw the issue with the infinite loops. With all the talk back and forth and changes and upgrades etc I agree with Charles Belov that I don't feel comfortable applying a patch, to a dev version, on something I'd like to use on a production site. I can deal with installing a dev, but a patched dev on a module that is having trouble being maintained.... well that's a little different.
I would like to thank EVERYONE that has worked on this issue. This is a wonderful community effort, I just wish we could push it to the next level and get it into dev at the very least. I'm all for helping with that.
Comment #466
ladybug_3777 CreditAttribution: ladybug_3777 commentedIs this issue, https://www.drupal.org/node/2395917, still an outstanding separate issue? I assume it is, but I saw fixes for workbench moderation were rolled into one of the patches, but then taken back out, and perhaps considered in again? I wasn't clear on it so I thought I'd ask the people that have worked closely with this fix. Thanks!
Comment #467
jimmynash CreditAttribution: jimmynash commentedI added the patch in #439 to two of my sites and so far things have been fine.
I was running version 7.x-1.0-rc1 in both cases. The process was this:
Testing consisted of:
I also tried adding a manual alias in the pathauto settings for the node itself and manually adding a redirect to an existing one. In both of these cases everything handled as it should and no circular redirects were caused.
I have two active sites in production using this patch now. If I run across any issues I'll report back.
HUGE thanks to everyone for their work on this long standing issue.
Comment #468
capellicApplied patch from latest dev (January 15, 2015) and it is working well!
Comment #469
betarobot CreditAttribution: betarobot commented#439 worked pretty well for me at live project where owners are changing blog titles often and erratically, so that could lead to loops before.
Comment #470
candelas CreditAttribution: candelas commentedHello you all :)
I think we have to solve two problems:... by one side to find a maintainer, as @cmseasy points out, and another to get this patch to dev (one very interesting solution for this is the one that @PQ proposes).
Maintainer ... @stefan.r wouldn't you, please, adopt this project... ? :) as you see, there is not anybody with the knowledge to make it... for a while... to push to dev the https://www.drupal.org/project/issues/redirect?text=&status=14&prioritie...
@PQ how many people/time to start with the process that you propose?
Let's do it! :)
Comment #471
stefan.r CreditAttribution: stefan.r commentedI'm currently not familiar enough with the redirect module to commit all those RTBC patches or to be fine with being a full-blown maintainer.
This patch however is widely tested, so if I were to be made "unofficial" maintainer I'd be OK to commit it, do a new release and deal with any issues that may come up as a consecuence :)
Comment #472
nicholasruunu CreditAttribution: nicholasruunu commented@stefan.r Why don't you step up as a co-maintaner and we just keep the searching for a co-maintainer label up?
Better we get something done than this just sitting and rot.
Comment #473
rcodina CreditAttribution: rcodina commented+1 to comment #472
This issue is taking too much long.
Comment #474
candelas CreditAttribution: candelas commented+1 to comment #472 :)
Comment #475
Alan D. CreditAttribution: Alan D. commented@stefan.r
Even if you tackle this and #905914: Merge global redirect functions into Redirect module, you will have closed off the two biggest irritants of this otherwise amazing module and big thumbs up from 138,873 users :)
These are by far the two most commented issues
https://www.drupal.org/project/issues/redirect?text=&status=All&prioriti...
Comment #476
PQ CreditAttribution: PQ commentedAs per #461, I have sent the following open email to the Drupal Association:
I'll update this thread with any response.
Comment #477
cmseasy CreditAttribution: cmseasy commentedI support #476, thanks PQ
Comment #478
ciss CreditAttribution: ciss commentedComment #479
hass CreditAttribution: hass commented@stefan.r: Have you field a issue to take over the project ownership or at least requested to become a co-maintainer?
Comment #480
stefan.r CreditAttribution: stefan.r commented@davereid is on parental leave, I caught him on IRC last week and he said he'd commit the issue when he could as it's been on his todo list for a while.
Comment #481
Reis Quarteu CreditAttribution: Reis Quarteu commentedPatch #249 works fine for me. Many thanks @stefan.r! :)
Comment #482
Dave ReidReviewed this. Ended up being very confused at why the hook_redirect_enable|disable were left in, since we already have hook_redirect_update(), so I removed those, in addition to the entity cache clearing, since that's already handled by redirect_save() as well. Moved the watchdog calls to redirect_change_status_multiple() instead. Could we get some confirmation from some testers for this to be the final version?
Not going to comment on anything else in here that was said while I was on paternity leave with a new baby (and still am).
Comment #484
Dave ReidThe update hook could have used some simplifications, I think the query was going to error on PostgreSQL due to not having all three fields included in the GROUP BY condition.
Comment #485
andresc75 CreditAttribution: andresc75 commentedHello, This is my first post on drupal.org
I think there is a related issue you may have to consider when preventing infinite loops with redirect module on path alias update.
This is my case:
- A site with Path aliases created using PathAuto with "transliteration" option not checked resulting in Ex.:
http://[BaseURLSite]/articulos/biomedicalización-del-envejecimiento
or
http://[BaseURLSite]/articulos/biomedicalizaci%C3%B3n-del-envejecimiento
- Several "Page Not found" errors on my log regarding with not transliterated URLs
- Want to change aliases converting special chars for preventing 404 and for better readeable URLs.
- Use auto update option in redirect module to auto create Redirects on updated aliases.
To solve this:
- Enabled transliteration on PathAuto for better URL compatibility.
- Edit a node and enable auto generate for updating URL Alias with the new PathAuto config
This results in:
- A new redirect record with old (not transliterated) URL -> node/[NodeID]
- An updated alias on PathAuto with the new transliterated URL -> node/[NodeID]
Problem:
When I try access the updated node with any URL (node/id, transliterated or not transliterated) i get an infintite loop error message.
A workaround solution for me was changing PathAuto URL pattern for this content type: Ex adding a node taxonomy term chaging "articulos/[node:title]" to "articulos/[node:taxonomy-vocabulary-4:name]/[node:title]"
By doing this, the NOT and the transliterated URL has an extra difference not regarding only with an ASCII special Char.
Other "solution" was disabling "auto create redirects when an url changes" in Redirect config. This made both URLs accesible but will generate duplicate content (not SEO fiendly) in transilterated and NOT URLs. And do not solves my original problem in detecting many "page not found" errors with not transliterated URLs.
My guess is
- PathAuto is not detecting any difference between both URLs when accesing to node
- Redirect (or pathauto) detects the diff on pathauto update and adds a redirect record
- This causes a transliterated path alias URL and a not transliterated path Redirect URL being the same causing an infinite loop
I don't know if this is a Redirect Issue, a PathAuto issue, a database config, or all above.
This was tested on Dev and Production servers:
Dev; Ubuntu 14.10 // Apache/2.4.10 // Mysql Ver:14.14 Dis: 5.5.40
Prod: CentOS 7 // Apache 2.4.6 // MariaDB 5.5.41 Ver: 15.1
Drupal 7.36 // Redirect 7.x-1.0-rc1 (and +13-dev) // Pathauto 7.x-1.2
Sory for my English!
Comment #486
stefan.r CreditAttribution: stefan.r commentedThose changes look good, however we are changing the update hook number to 7100 but a significant amount of people already run some version of this patch on production systems. Considering sometimes very basic questions come up, I'm quite sure a few of them may miss update hook #7101 if we start changing numbers around. Maybe we can add an empty 7100 update hook instead?
As to the implications of the actual changes:
1. The new query looks good, it doesn't have the
GROUP BY
anymore which should still be fine, it just means that the array of redirect IDs to update may have some duplicates, which should have no practical implications.2. Removing
hook_redirect_disable()
andhook_redirect_disable()
should be fine too, as we're already invoking presave/update hooks inredirect_save()
, which is the only place where the disable/enable hooks were being invoked anyway.The only implication is that we would miss the chance to react to a redirect being enabled/disabled (nor would anything appear in the log) if another module changes the status back to whatever it was in the presave/update hooks, but then it's not actually "truly" being enabled/disabled anyway, so I guess that's fine.
3. It seems the entity cache clear code was just copy-pasted from
redirect_delete_multiple()
, and I don't see anything happening that would require a cache clear between where that cache clear used to be and the existing cache clear inredirect_save()
. So that's OK too.4. Moving the watchdog messages to where they are now should be fine, however there is no more check that looks whether we are actually moving from disabled to enabled or viceversa, ie. it will still say "X has been disabled" even if X was already disabled, which is not a big deal either.
Comment #487
stefan.r CreditAttribution: stefan.r commentedComment #488
stefan.r CreditAttribution: stefan.r commentedAh, seems we already had the upgrade hook discussion over in comments #433 - #440, where we suggested to either remove 7100 and start with 7101, or to add an empty 7100 update hook.
Comment #489
Dave ReidOk I see what happened with the update hook. Let's just leave the existing one alone. It was added for a reason and we don't just get rid of empty update hooks because we feel like it. That added unnecessary confusion.
This also makes redirect_change_status_multiple() a no-op for redirects that already match the status parameter, and make the {redirect}.status column a tiny int column instead of unsigned, which is unnecessary for the data it stores.
Comment #490
stefan.r CreditAttribution: stefan.r commentedI'm not sure that the original update hook actually triggered a registry rebuild. I think that happens after a drush updatedb and not after every individual update hook? So the description may be misleading and I also don't remember why a registry rebuild & entity info refresh would be required. I think that was about an error with a new class from redirect dev not being found. Not really in scope of this issue but would still be good to fix.
Overall the patch looks ready to me now, maybe it just needs one or two further reviews now?
@Dave Reid can we please do a new release after this patch goes in? For any post-release followup specific to to this issue, I'll be happy to keep on top of this :)
Comment #491
kylebrowning CreditAttribution: kylebrowning commentedNot that I've been involved a lot in this ticket, but happy to co-maintain if needed.
patch #488 worked for me.
Comment #493
stefan.r CreditAttribution: stefan.r commented@kylebrowning (and others) please can you do a review of this interdiff between Dave Reid's latest patch (#489) and the latest RTBC patch (#439?)
Would also be good if anyone could do some manual testing.
Comment #494
stefan.r CreditAttribution: stefan.r commentedComment #495
stefan.r CreditAttribution: stefan.r commentedTested this manually.
Dave Reid's changes all were OK.
I did find a few other issues though:
1. Bulk operations in admin/config/search/redirect were broken, because of this:
2. The watchdog message was in plural if there was only 1 redirect.
3. The update hook combines two actions that shouldn't be combined. If we fail in the middle of this update hook, we can't re-run it because the field has already been added.
4. Added comment about no-op behavior when there's no change of status. Maybe people do write code that triggers on hook_save and wonder why it isn't running when a redirect goes from disabled to disabled.
Comment #496
stefan.r CreditAttribution: stefan.r commentedAnd the thing in this interdiff shouldn't have been changed in that previous patch.
Comment #497
stefan.r CreditAttribution: stefan.r commentedReviewed the older comments and remembered what the empty update hook was about. Some other issue introduced that, on the assumption that it would trigger a registry rebuild. However, it doesn't, that only happens at the end of an update run. So we had changed it to:
However, in #418 someone took it out, saying:
But we *did* call that, when we change the status of redirects in update hook #7102. So that should've stayed in there at that point.
Comment #498
stefan.r CreditAttribution: stefan.r commentedSo I looked into this and in update hook 7102 we changed from redirect_save() to a database query directly, and we only call the entity controller anymore to do a reset of the redirect static entity cache.
I think the conservative thing to do here is to remove that call to the entity controller (as we may not know where its class is located yet before having done a registry rebuild), and just deal with the fact that the static entity cache may not know yet about the changed redirect status -- for now this has 0 practicaly implications.
However, the issue of the missing registry rebuild / entity info rebuild remains. But as the main priority here is getting this patch committed, and the lack of this doesn't currently break anything, I don't think we should hastily re-add these and potentially introduce further issues. Doing cache clears in the middle of an upgrade is always potentially dangerous (ie. when distribution upgrades change multiple modules at once).
The thing to do for now may be to comment this in code and add a @todo (which is what this patch does). Also filing a followup for the broken update hook #7100, which should be out of scope as far as this issue is concerned: #2485459: Update hook 7100 does not do a registry rebuild or entity info cache clear.
Attaching an interdiff with Dave's latest patch for his review.
Comment #499
stefan.r CreditAttribution: stefan.r commented80 cols fix
Comment #500
heddnVariables should be passed to watchdog, rather than concatenating them into the message.
Comment #501
heddnThis should read:
So if a disabled redirect is disabled, no redirect_save() is...
Comment #502
stefan.r CreditAttribution: stefan.r commentedComment #503
heddnNit: comment line length.
This was dropped from #444. The count is returned by the db_update. Use it instead.
Build the URL for the edit page using url() and insert using variable substitution.
Comment #504
heddnUpdated issue summary with suggested commit message.
#503.3 can be safely ignored. It was already using the alternate method. Out of scope of fixing in this issue.
Comment #505
stefan.r CreditAttribution: stefan.r commentedFixed 1 and 2. Leaving 3 alone as it's merely inconvenient for translators, not an actual problem. We don't want to introduce new bugs and the
l()
documentation on drupal.org also usest('<a href="@link">link<a/>')
as an example.Reverted changes to that watchdog call from #500 as it's out of scope for this patch. Formatting singular/plural strings right into watchdog isn't something that can easily be done, so it was the way it was for a reason. Ideally it would have said "redirect(s)", but that's introducing a new translatable string.
Instead, I fixed the watchdog call that _this_ patch introduced :)
Comment #506
stefan.r CreditAttribution: stefan.r commentedComment #507
stefan.r CreditAttribution: stefan.r commentedThat was one last change I discussed with @heddn, we thought this should be stricter.
that previous interdiff was faulty, attached one is the correct one.
Comment #511
heddnThis should be a fairly easy thing to troubleshoot. Follow https://www.drupal.org/node/30011, and add breakpoints in redirect_save() and redirect_change_status_multiple().
Comment #512
stefan.r CreditAttribution: stefan.r commented@heddn I looked into this and we may want to stick with the weak typing and allow status to be either an integer or a string. I think it's a string on the redirect object for instance.
Comment #513
stefan.r CreditAttribution: stefan.r commentedInterdiff with Dave Reid's patch in #489
Comment #514
rroblik CreditAttribution: rroblik commentedCan we expect a commit in
dev
version ?Thanks
Comment #515
stefan.r CreditAttribution: stefan.r commentedYes, at some point, but we probably first need to get this back to RTBC. Any further reviews will help toward getting this committed :)
Comment #516
stefan.r CreditAttribution: stefan.r commentedComment #517
klokie CreditAttribution: klokie commentedPatch in #516 works for me (on a multilingual site). Would be great to get this RTBC as it affects all of my projects!
Comment #518
cmseasy CreditAttribution: cmseasy commentedPatch #516 tested in a development environment.
During the test I never seen an error or warning message.
Overall test results: ok.
1) First title (node made):
url alias is made.
no redirect.
Result: ok.
2) Change title (url change):
A new alias is made, removing the old alias from (1).
A redirect is made from old (first title) alias to node/#.
Result: ok.
3) Change title back to 'first title' (url change):
A new alias is made, equals the 'first title' alias (1).
A redirect is made from old 'çhanged title' alias made in (2) to node/#.
The 'first title' redirect made in (2) changed status to Disabled.
Result: ok.
Comment #519
bdanin CreditAttribution: bdanin commentedHere is my testing on patch #516:
Update from 7.x-1.0-rc1 to 7.x-1.x-dev, and ran update.php
Then apply patch #516, run update.php
Removed infinite redirect (I only had one, and it also worked in an instance with 0), and everything appears to work.
The issue I've found is that if I take the latest 7.x-1.x-dev, apply patch from #516, and then push the code to the server, I get locked out of the site and there is an error screen. It's the same error screen as if you just apply #516, but the difference is that I cannot sign in and run update.php
The concern here is that if this gets merged into dev, then it will be really hard to update from 1.0-rc1 to dev on a live site.
Everything else seems to be working well though.
Comment #520
stefan.r CreditAttribution: stefan.r commentedIt is unclear what you mean here, could you clarify?
Case 1: 1.0-rc1 -> 1.x-dev -> update.php -> patch -> update.php -> all is OK?
Case 2: 1.0-rc1 -> 1.x-dev+patch -> update.php -> gives an error?
Is there any way we can reproduce this on a new drupal install? Which error screen do you get when you go to update.php? Is the problem that you cannot login before running update.php? What if you are already logged in before pushing the new code, can you run update.php then?
Comment #521
bdanin CreditAttribution: bdanin commentedLet me try a more structured version of testing this (hoping I have time), I think the error is
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'status' in 'where clause': SELECT redirect.rid AS rid FROM {redirect} redirect WHERE (status = :db_condition_placeholder_0) AND( (source LIKE :db_condition_placeholder_1 ESCAPE '\\') OR (source = :db_condition_placeholder_2) )AND (language IN (:db_condition_placeholder_3, :db_condition_placeholder_4)) ; Array ( [:db_condition_placeholder_0] => 1 [:db_condition_placeholder_1] => node/631 [:db_condition_placeholder_2] => [:db_condition_placeholder_3] => en [:db_condition_placeholder_4] => und ) in redirect_fetch_rids_by_path() (line 575 of /sites/all/modules/contrib/redirect/redirect.module).
Comment #522
stefan.r CreditAttribution: stefan.r commentedAre you sure you get that error in update.php? That seems odd...
Wenever we're about to install a new version of a module we should assume our site may be broken until any update hooks have run, see also https://www.drupal.org/node/250790.
So steps would usually be:
put site in maintenance mode -> install new code -> run update hooks
So if what you were trying to do was:
install new code -> log in -> run update hooks
That may have need to be:
log in -> install new code -> run update hooks
Comment #523
bdanin CreditAttribution: bdanin commentedYes, I agree, you must sign into the site before adding the updated code.
when trying to sign into the site at /user, here is the problem I encountered:
Case 1: 1.0-rc1 -> 1.x-dev -> update.php -> patch -> update.php -> all is OK
Case 2: 1.0-rc1 -> 1.x-dev+patch -> update.php -> if already signed-in, then you can run update.php
I'll note that going from 1.0-rc1 -> 1.x-dev => you can still sign into the site, and the site itself works but 1.0-rc1 -> 1.x-dev+patch => broken site with the error I posted above until updates are run (the error I posted was not from update.php but the error that breaks the site).
Overall, this isn't a major problem because like you said, you should already be signed into the site with maintenance mode turned on before adding new code to the server, and then you can go from 1.0-rc1 -> 1.x-dev+patch -> update.php, and I've now tested that this does work as it should for me.
Comment #524
klokie CreditAttribution: klokie as a volunteer commentedIn case it helps anyone, here's how I run the update from the command line (after already having tested it on a development site per #518, and also backing up the database). This worked successfully for 3 sites so far, taking less than 1 minute to run.
Thanks for the patch. Marking as RTBC, hope that's ok. Cheers!
Comment #525
stefan.r CreditAttribution: stefan.r commented#523: I think we can live with that, maybe put a note in the rc2 release notes just in case.
The update.php script has clear instructions re what we can do other than logging in -- we don't /have/ to be logged in to do an update.
Thanks klokie for the review.
Comment #526
valentin schmid CreditAttribution: valentin schmid commentedWe're just testing patch #516 together with patch #195 from https://www.drupal.org/node/905914.
No problem so far. Just works great.
Thank you.
Comment #527
bdanin CreditAttribution: bdanin commented#525, that would be great. Having this out there as an rc2 release would be very helpful, so I definitely support RTBC.
Just a quick note that a lot of production machines won't necessarily have drush, but I was still able to test upgrading to this patched version several times successfully without using drush.
Comment #528
GoZ CreditAttribution: GoZ commented1/ Create node : title1 (node/1)
2/ Rename to title2 : create redirect title1 -> node/1 enable
3/ Create node : title1 (node/2) : disable redirect title1->node/1. node/2 is available at /title1
4/ Edit node/1 and enable redirect title1->node/1. title1 redirect now to node/1. node/2 is now not available with title1 path.
From data for this redirect is now node/2->node/1.
No message is displayed and it's possible to enable this previous redirect.
Are you agree with that ?
Another thing, we keep disabled redirect with same path. This could be deleted instead of being disabled.
1/ Create node : title1 (node/1)
2/ Rename to title2 : create redirect title1 -> node/1 enable
2/ Rename to title1 : create redirect title2 -> node/1 enable. Disable title1->node/1
I agree to keep disabled redirect when it could be useful, but in this case, it's not.
Comment #529
stefan.r CreditAttribution: stefan.r commentedThe first half of that comment I don't understand. How should this be fixed / what kind of message should be displayed in your opinion?
As to the second half, I think it's fine to keep the old redirect and disable it, just for consistency or in case it was manually created.
Comment #530
GoZ CreditAttribution: GoZ commented@stefan.r Following first half steps, you can enable a redirect which make another node unavailable. I think we should not allow a redirect to be enable if another node has same path or at least display a message like "While redirect xxx is enabled, node 2 will not be accessible."
Comment #531
stefan.r CreditAttribution: stefan.r commented@GoZ just to reiterate what you were trying to say:
'cats' -> node/1
becomesnode/2 -> node/1
).It's logical for node/2 to be inaccessible though, as there's now a redirect away from it.
So while this may be odd behavior, in a way it's expected.
As to your suggestions, I'm not sure disallowing the enabling of that redirects that have the alias of an existing node in the "from" field is the right solution. We may restrict legitimate use cases there, and I'm worried about the complexity it would add to this patch.
I agree we may want to warn users with an error message when there's possibly odd behavior, but the problem with the error message you suggest is that it only seems to add to the confusion ("While redirect node/2 -> node/1 is enabled, node 2 will not be accessible.")
Maybe this should be a non-critical followup?
Comment #532
heddnAll the feedback from the issue summary is addressed and a review of the feedback back through the past few hundred comments. So I'll +1 on the RTBC.
Comment #533
GoZ CreditAttribution: GoZ commented@stefan.r I agree with you this is not critical and could be improved in another issue. So this one could be commited.
+1 for RTBC (Yeah!)
Comment #534
hanoiiA little bit (completly) off-topic, but wanted to share an offspring of this issue.
Keeping up with it was driving me crazy drupal.org-navigation-wise, so I contributed this for dreditor:
https://github.com/dreditor/dreditor/pull/255
Comment #535
Leeteq CreditAttribution: Leeteq commentedAgreeing with Stefan.r and others here, it would be very practical if this was released as RC2 immediately after -dev is updated, so we have a clear before/after point.
Comment #536
Dustin@PI CreditAttribution: Dustin@PI commented@stefan.r says in comment 531 "So while this may be odd behavior, in a way it's expected." ... I agree It is slightly odd behavior but it's useful, one of my sites relies on it. Having a warning message in that scenario is useful, but I feel that should be a separate feature request. I will not get to try the patch until tomorrow, but don't let that stop the RTBC from being switched to fixed.
Comment #537
razgriz.one CreditAttribution: razgriz.one commentedI have applied patch from #516.
Tested:
1) Old posts with infinite loop warnings before update
Result: After updating, infinite loop was removed by disabling URLs responsible for infinite loops
2) Added new content after update, then renamed content to create infinite loop
Result: Patch prevented redirect from creating infinite loop by disabling URL redirects by default
As far as I can tell, the patch is working acceptably.
Comment #538
blacklabel_tom CreditAttribution: blacklabel_tom at Edo commentedHi,
I applied the patch in #516 and it working as expected.
Cheers
Tom
Comment #539
Elijah LynnLGTFM!
Comment #540
Dustin@PI CreditAttribution: Dustin@PI commentedI have tested on SimplyTest.me on a fresh install, and one of my teammates tested on our the dev version of our complicated site and both worked well.
Any idea when there might be a new Beta (or even a dev release)?
Comment #541
hanoiiOnly a quick bump/reminder not to lose the momentum that the issue got lately, it seemed close to be accepted.
Comment #542
JackProbst CreditAttribution: JackProbst at TEN7 commentedI've tested and applied the patch in #516. It works as intended. +1 ready to be committed.
Comment #543
stefan.r CreditAttribution: stefan.r commentedYes this has been RTBC long enough now, let's get this in.
I think only @Dave Reid can commit this, he recently became a dad so it may take a while still :)
Comment #545
Dave ReidCommitted #516 to 7.x-1.x. Thanks everyone for your patience and diligence. I'm evaluating adding a co-maintainer this week so situations like this do not happen in the future.
Comment #546
stefan.r CreditAttribution: stefan.r commentedGreat stuff! Will a new release be tagged soon?
/edit: Looks like yes per #2505299: Is it time to publish another release?, thanks!
Comment #547
Dave ReidYes, prepping a RC2 release for today after reviewing the issue queue. Next release targeted is 1.0.
Comment #548
hanoiiI wonder if @stefan.r would like to be one? He has proven to be the key promoter (and patcher) of this issue and I expect him to be very familiar with the module, but not sure if he has the time or anything else might prevent him to properly be one.
Comment #549
ar-jan CreditAttribution: ar-jan as a volunteer commentedThanks Dave Reid, stefan.r and everyone else who worked on fixing this!
Comment #550
John Bickar CreditAttribution: John Bickar commented+1. Bravo, everyone. I have been holding off on updating the Redirect module on over 1,200 D7 sites due to this issue. Now I can update.
Thank you!