Problems with custom_url_rewrite_outbound
checker - October 29, 2008 - 16:24
| Project: | Global Redirect |
| Version: | 6.x-1.x-dev |
| Component: | Code |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | duplicate |
Description
If you are using the function custom_url_rewrite_outbound() and custom_url_rewrite_inbound() global redirect is getting into an endless loop.
function custom_url_rewrite_outbound(&$path, &$options, $original_path) {
if (preg_match('|^user(/.*)|', $path, $matches)) {
$path = 'new-user-url'. $matches[1];
}
}
function custom_url_rewrite_inbound(&$result, $path, $path_language) {
if (preg_match('|^new-user-url(/.*)|', $path, $matches)) {
$result= 'user'. $matches[1];
}
}
#1
You can solute this problem with following code - better ideas are welcome!
before:
if ($_REQUEST['q'] != $prefix . $alias) {
drupal_goto($alias, $query_string, NULL, 301);
}
add:
if (function_exists('custom_url_rewrite_inbound')) {custom_url_rewrite_inbound($custom_path, $_REQUEST['q'], '');
if($custom_path != '') {
$_REQUEST['q'] = $custom_path;
}
}
#2
Surely we'd need to apply the custom_url_rewrite_inbound to $_REQUEST['q'] at the very beginning so it effects all the redirects (frontpage, '/0' trimming, etc).
Also - is this problem due to not using custom_url_rewrite_inbound OR is it relating to outbound (as the subject suggests)?
Any thoughts?
#3
The subject is wrong. It should be mean "Problems with custom_url_rewrite_inbound". I think there are many situations that need both functions in the interplay use. But the problem with global redirect is just to find in custom_url_rewrite_inbound().
-I used this code above for a productiv website and there are no problems.
-I used custom_url_rewrite_inbound() in settings.php.
#4
I have a better patch here. And it is a severe problem. First here are my rewrite functions
<?php
/**
* rewrite incoming urls to drupal urls
*
* @param result
* the resulting path, input value is the current path, and function should
* change this value
*
* @param path
* the path (?q=PATH)
*
* @param path_language
* not used by us. What do with it?
*/
function custom_url_rewrite_inbound(&$result, $path, $path_language) {
global $conf;
// remove community url prefix which shouldn't be used as an arg()
// the homepage is an example since apache strips the last / so we test differently for this case
if (!empty($conf['community_config_url_prefix'])) {
if (substr($conf['community_config_url_prefix'], 0, -1) == $result) {
$result = $conf['site_frontpage'];
}
elseif (strpos($result, $conf['community_config_url_prefix']) === 0) {
$result = substr_replace($result, '', 0, strlen($conf['community_config_url_prefix']));
}
}
static $uid_cache = array(); // static cache the uids
$args = explode('/', $result);
if (custom_url_skip($args)) {
return;
}
if (($args[0] == 'user' || $args[0] == 'blog') && isset($args[1])) {
if (isset($uid_cache[$args[1]])) {
$uid = $uid_cache[$args[1]];
}
else {
$uid = ($GLOBALS['user']->uid && $args[1] == $GLOBALS['user']->name) ? $GLOBALS['user']->uid : db_result(db_query("SELECT uid FROM {users} WHERE name ='%s'", $args[1]));
$uid_cache[$args[1]] = $uid;
}
$result = str_replace($args[0] .'/'. $args[1], $args[0] .'/'. $uid, $result);
}
}
/**
* rewrite internal paths into user facing paths
*
* @param path
* This is the pass by refrence variable. This value should be changed to the
* desired path
*
* @param options
* array of link options. @see url()
*
* @param orginal_path
* the orginal, internal path generated by url() function
*/
function custom_url_rewrite_outbound(&$path, &$options, $original_path) {
global $conf;
static $user_names = array();
$arg = explode('/', $original_path);
if (($arg[0] == 'user' || $arg[0] == 'blog') && is_numeric($arg[1])) {
if ($arg[1] == $GLOBALS['user']->uid) {
$name = $GLOBALS['user']->name;
}
else {
// the same username can appear more than once on a page so we static cache the result
if (!isset($user_names[$arg[1]])) {
$name = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $arg[1]));
$user_names[$arg[1]] = $name;
}
else {
$name = $user_names[$arg[1]];
}
}
// Drupal paths are case senstive, since it does things like arg(0) == 'node'
// make sure usernames are lowercase for paths & links as well
$name = strtolower($name);
$path = str_replace($arg[0] .'/'. $arg[1], $arg[0] .'/'. check_plain($name), $original_path);
}
// add in community url prefix to all URLs to segment content but not act as a real arg()
$path = $conf['community_config_url_prefix'] . $path;
}
?>
Basically, what they do is rewrite the user/ID/* urls to user/NAME/*. This in conjunction with global redirect makes user/NAME/* redirect forever.
Why this happens
drupal_get_path_alias() returns either an alias url (from the url_alias table) or the drupal_normal_path (user/1/*). Global redirect assumes that if the $alias (which is from drupal_get_path_alias()) doesn't match the $_REQUEST['q'] then we need to redirect. The problem with that is an aliased path can come from the url_alias table, and it can come from custom_url_rewrite_* (which drupal_get_path_alias() ignores). So the $_REQUEST['q'] = user/scott but $request = user/1 and alias = user/1.
Thus this simple patch.
#5
plz review
#6
patch in #4 works great for me - thanks Scott :)
#7
if looking for ways to test this patch try drupal.org/project/spaces
That too will make globalredirect cry out in pain :-D, this patch should fix that.
#8
It fixed my use case which was just a simple menu item path rewrite, where it would get stuck in a loop.
I think this will also fix the issue when using this module with the subdomain module. Will be testing that later this week.
Thanks again
Ben
#9
After testing, this patch doesn't fix the issue with subdomain module after all - that needs some further changes to work.
#10
DOH! this breaks the de-slashing.
#11
Here is a naive fix.
#12
Ok so this is a real fix :-D
Basic idea is we need to find the 'alias'. And it can exists in two spots, the url_alias table or via custom_url_rewrite_* functions.
I like this patch so much better, its clean.
#13
#346911: Redirect Loop and custom_url_rewrite ignored