我的目标是从这些路径重定向用户:
/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]
但这会进入无限重定向循环。我认为为URI添加RewriteCond
会有所帮助,但是来自docs:
注意:
RewriteRule
模式匹配后正在处理条件。
显然RewriteCond
在我的用例中没什么用处。
查看Rewrite Flags docs,S
标志似乎正是我正在寻找的内容:
如果当前规则匹配,则此标志强制重写引擎按顺序跳过下一个num规则。使用它来创建伪if-then-else结构:then子句的最后一条规则变为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重写为旧URL,然后在PHP中检查$_SERVER['REQUEST_URI']
是否与脚本开头的新格式匹配,否则301重定向到新URL。
尽管如此,我想知道这是否仅仅与.htaccess
有关?或者,如果有人能够解释我是如何/为什么通过上述重写规则获得无限循环,我将不胜感激。
答案 0 :(得分:1)
问题在于规则在.htaccess
文件中,正如docs所说,此文件在每次重写循环后都会重新解析,因为它可能适用于.htaccess
在另一个目录中。因此,你的L
标志都是徒劳的。
我环顾四周,如果你真的无法将重写规则放在主apache配置中,我可以提供以下kludge:因为在重写运行之间没有更新Server-Variables THE_REQUEST
,所以可以从那里结束“浏览器可见URL”并防止在那种情况下重写:
# 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]
我认为还有另一个变量保持不变,但现在我找不到它。也许是其他人?