2013-02-12 130 views
1

我的目标是从这些路径将用户重定向:重写规则,以新的URL和内部重写旧

/foo/index.php 
/foo/ 

/index 

而且具有/index负荷/foo/index.php原始内容。

这可能性在.htaccess

到目前为止,我已经试过:

RewriteRule ^foo/(index\.php)?$ /index [R=301,QSA,L] 
RewriteRule ^index$ /foo/index.php [QSA,L] 

但这进入一个无限循环的重定向。我想添加一个RewriteCond的URI会有所帮助,但是从docs

注:RewriteRule的格局相匹配后条件正在处理中。

显然RewriteCond在我的使用情况下不会有太大用处。

通过Rewrite Flags docs看,该S标志似乎正是我在寻找:

此标记强制重写引擎跳过序列中的下一NUM规则,如果当前的规则相匹配。使用这个来伪造if-then-else结构:then-clause的最后一条规则变成skip = N,其中N是else子句中的规则数目。

所以我已经试过:

RewriteRule ^index$ /foo/index.php [QSA,L,S=1] 
RewriteRule ^foo/(index\.php)?$ /index [R=301,QSA,L] 

虽然,因为我有L标志,该标志S似乎有点多余。尽管如此,我认为这种逻辑似乎是正确的,尽管这仍然处于无限的重定向循环中。

现在我正在使用PHP的解决方法。首先,Apache在内部将新URL重写为旧的,然后在PHP中检查$_SERVER['REQUEST_URI']是否与脚本开头的新格式相匹配,否则将301重定向到新URL。

虽然,我想知道是否可以单独使用.htaccess?或者如果任何人可以解释如何/为什么我会通过上面的重写规则获得无限循环,我将不胜感激。

回答

1

麻烦的是,这些规则在.htaccess文件,为docs说,这个文件每隔rewite循环之后重新解析,letst它可能会在不同的目录已经适用于.htaccess。因此你的L标志都是徒劳的。

我看了看周围,如果你真的不能把你的重写规则放在主要的apache配置中,我可以提供以下kludge:因为服务器变量THE_REQUEST在重写运行之间没有更新,所以可以推断出“浏览器显示的网址”从那里和防止改写在这种情况下:

# external redirect to /index (unless browser already shows /index plus query params) 
RewriteCond %{THE_REQUEST} !^\w+\ /index(\?.*)?\ HTTP/1..$ 
RewriteRule ^foo/(index\.php)?$ /index [R=301,QSA,L] 

# internal redirect for /index 
RewriteRule ^index$ /foo/index.php [QSA,L] 

我认为有也是不变的另一个变量,但现在我找不到它。也许是别人?

+0

+1,正如你所说的,唯一合乎逻辑的解释是'L'实际上并没有结束重写,而是开始一个新的重写循环?但是,如果我按照你所说的将这些放在主要配置文件上,它是否可以解决这个问题?现在去测试。 – 2013-02-12 23:28:34

+1

噢,是的,我应该先阅读完整的'L'标志文档。我已经更新了你的正则表达式,以便始终在请求路径名称开头匹配'/ index':'RewriteCond%{THE_REQUEST}!^ \ w + \/index(?:\?。*)?'现在它工作得很好, 谢谢。 – 2013-02-13 00:09:18

+0

是的,你的正则表达式看起来更好,我更新了我的答案 – 2013-02-13 08:08:26