将规则重写为新 URL,并在内部重写为旧 URL

RewriteRule to new URL and internally rewrite to old one

提问人:Fabrício Matté 提问时间:2/13/2013 最后编辑:Fabrício Matté 更新时间:2/13/2013 访问量:790

问:

我的目标是将用户从以下路径重定向:

/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

注意:在模式匹配后,正在处理条件。RewriteRule

所以显然在我的用例中没有多大用处。RewriteCond

浏览 Rewrite Flags 文档,该标志似乎是我要找的:S

如果当前规则匹配,则此标志强制重写引擎按顺序跳过下一个 num 规则。用它来制作伪 if-then-else 构造:then-子句的最后一条规则变为 skip=N,其中 N 是 else-clause 中的规则数。

所以我试过了:

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

不过,由于我有旗帜,这面旗帜似乎有点多余。尽管如此,在我看来,这个逻辑似乎是正确的,尽管这仍然处于无限重定向循环中。LS

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

不过,我想知道这是否可能只与此有关?或者,如果有人能解释我如何/为什么使用上面的重写规则获得无限循环,我将不胜感激。.htaccess

php apache .htaccess mod-rewrite url-rewriting

评论


答:

1赞 Clemens Klein-Robbenhaar 2/13/2013 #1

麻烦的是规则在一个文件中,正如文档所说,这个文件在每次 rewite 循环后都会被重新解析,因为它可能适用于不同目录中的 a。因此,你的旗帜都是徒劳的。.htaccess.htaccessL

我环顾四周,如果你真的不能把你的重写规则放在主apache配置中,我可以提供以下的kludge:因为服务器变量在重写运行之间没有更新,所以可以从那里得出“浏览器可见URL”的结论,并在这种情况下防止重写: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赞 Fabrício Matté 2/13/2013
+1,正如你所说,唯一合乎逻辑的解释是,它实际上并没有结束重写,而是开始了一个新的重写循环?不过,如果我像你说的那样把它们放在主会议上,它会解决问题吗?现在要测试。L
1赞 Fabrício Matté 2/13/2013
哦,是的,我之前应该阅读完整的标志文档。我已经更新了您的正则表达式以始终在请求路径名的开头匹配:它现在工作得很好,谢谢。L/indexRewriteCond %{THE_REQUEST} !^\w+\ /index(?:\?.*)?
0赞 Fabrício Matté 2/13/2013
此外,更具体地说,我们可以尝试匹配旧格式,而不是否定新格式: - 仅匹配请求,因为在重定向的情况下数据会丢失,因此 POST URL 仍然可以使用旧 URL,以便在涉及 POST 请求时轻松发现和更新内部链接。如果将所有 url 从给定路径内重定向到根目录,匹配目录也很有用,但这超出了问题的范围,没关系。RewriteCond %{THE_REQUEST} ^GET\ /foo/.*GETPOSTRewriteCond %{THE_REQUEST}=]