如何将子目录重定向到目录和查询字符串?

时间:2015-08-18 13:10:38

标签: php apache .htaccess mod-rewrite

我正在尝试使用.htaccess和mod_rewrite来重定向我网站上的网址。

我想拥有它,以便/questions/12345/users/12345分别重定向到/questions/display.php?id=12345/users/display.php?id=12345

喜欢添加一个类似Stack Exchange的快捷方式,其中/q/12345/6789被重写为/questions/display.php?id=12345&refer=6789

到目前为止,看过several sources后,我得到了这个:

RewriteEngine On
RewriteRule ^users/([^/]+) /users/display.php?id=$1 [NC]
RewriteRule ^questions/([^/]+) /questions/display.php?id=$1 [NC]
RewriteRule ^q/([^/]+)/([^/]+) /questions/display.php?id=$1&referer=$2 [NC]

但是,当我导航到/questions/12345时,我收到500内部服务器错误 - 很明显,这不起作用。

在查看Apache错误日志时,它会显示正在发生的事情:

  

AH00124:由于可能的配置错误,请求超出了10个内部重定向的限制。如有必要,使用'LimitInternalRecursion'增加限制。使用“LogLevel debug”获取回溯。

这里出了什么问题,应该我做了什么?

2 个答案:

答案 0 :(得分:2)

问题在于重写引擎循环,因此您重写的内容最终会再次匹配相同的规则。您可以尝试添加一些条件来防止这种情况:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^users/([^/]+) /users/display.php?id=$1 [NC,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^questions/([^/]+) /questions/display.php?id=$1 [NC,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^q/([^/]+)/([^/]+) /questions/display.php?id=$1&referer=$2 [NC,L]

答案 1 :(得分:1)

您的重定向正在发挥作用。 : - )

注意正则表达式原子([^/]+)。这意味着“任何一个或多个不是正斜杠的字符的运行”。文字display.php?id=匹配,因此您首次要求

/users/123

你被改写为

/users/display.php?id=123

但重定向并不止于此。新URL也会通过重写引擎,写入:

/users/display.php?id=display.php?id=123

您的重写网址会一直重写,直到您达到限制为止,如日志中所述。

要解决此问题,您可以使初始正则表达式更具限制性。

RewriteRule ^users/([0-9]+) /users/display.php?id=$1 [NC]

您还可以告诉重写引擎特定规则是“最后”规则,因此它不会重新处理该行(或通过任何其他规则运行它):

RewriteRule ^users/([0-9]+) /users/display.php?id=$1 [NC,L]

最后,如果请求的路径是文件,Apache可以通过告诉Apache不要应用重写规则来添加额外的保护:

# Exempt requests to directories...
RewriteCond %{REQUEST_FILENAME} !-d

# Exempt requests directly to files...
RewriteCond %{REQUEST_FILENAME} !-f

# Rewrite /users/###
RewriteRule ^users/([0-9]+) /users/display.php?id=$1 [NC,L]

这是一种带有腰带和背带的解决方案,但你想要以任何可能的方式应用保护的想法是合理的。