Lig*_*ica 5 .htaccess http-redirect
今天早些时候,我正在帮助一个.htaccess用例的人,并提出了一个有效的解决方案,但我自己无法弄明白!
他希望能够:
index.php?id=3&cat=5index/3/5/index.php?id=3&cat=5最后两个步骤相当典型(通常来自用户index/3/5首先进入),但第一步是必需的,因为他的网站中仍然有一些旧格式的链接,无论出于何种原因,都无法更改它们.所以他需要支持这两种 URL格式,让用户总是看到美化的格式.
经过多次考验后,我们想出了以下.htaccess文件:
RewriteEngine on
# Prevents browser looping, which does seem
# to occur in some specific scenarios. Can't
# explain the mechanics of this problem in
# detail, but there we go.
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]
# Hard-rewrite ("[R]") to "friendly" URL.
# Needs RewriteCond to match original querystring.
# Uses "?" in target to remove original querystring,
# and "%n" backrefs to move its components.
# Target must be a full path as it's a hard-rewrite.
RewriteCond %{QUERY_STRING} ^id=(\d+)&cat=(\d+)$
RewriteRule ^index\.php$ http://example.com/index/%1/%2/? [L,R]
# Soft-rewrite from "friendly" URL to "real" URL.
# Transparent to browser.
RewriteRule ^index/(\d+)/(\d+)/$ /index.php?id=$1&cat=$2
Run Code Online (Sandbox Code Playgroud)
虽然它似乎是一个有点奇怪的用例(" 为什么不首先使用正确的链接? ",你可能会问),只是顺其自然.无论原始要求如何,这都是场景,这让我很生气.
没有第一条规则,客户端进入请求循环,尝试GET /index/X/Y/重复并获取302每次.检查REDIRECT_STATUS使一切顺利进行.但是我会想到,在最终规则之后,不再提供规则,客户不会再提出任何请求(注意,不[R]),一切都会变成肉汁.
那么......当我拿出第一条规则时,为什么这会导致请求循环?
由于无法修改您的设置,我不能肯定地说,但我相信这个问题是由于 mod_rewrite 的以下相对神秘的功能造成的:
当您在每个目录上下文中操作 URL/文件名时,mod_rewrite 首先将文件名重写回其相应的 URL(这通常是不可能的,但请参阅下面的 RewriteBase 指令以了解实现此目的的技巧),然后启动一个新的内部子请求使用新的 URL。这将重新启动 API 阶段的处理。
(来源:mod_rewrite 技术文档,我强烈建议阅读此内容)
换句话说,当您RewriteRule在.htaccess文件中使用 a 时,新的重写的 URL 可能会映射到文件系统上完全不同的目录,在这种情况下,.htaccess原始目录中的文件将不再适用。RewriteRule因此,只要文件中的a.htaccess与请求匹配,Apache 就必须使用修改后的 URL从头开始处理。这意味着,除其他外,每一项RewriteRule都会被再次检查。
就您而言,发生的情况是您/index/X/Y/从浏览器访问。文件中的最后一条规则.htaccess将被触发,将其重写为/index.php?id=X&cat=Y,因此 Apache 必须使用 URL 创建一个新的内部子请求/index.php?id=X&cat=Y。这与您之前的外部重定向规则相匹配,因此 Apache 将 302 响应发送回浏览器以将其重定向到/index/X/Y/. 但请记住,浏览器从未见过该内部子请求;据它所知,它已经开始了/index/X/Y/。因此,您看起来好像被重定向到/index/X/Y/同一个 URL,从而触发了无限循环。
.htaccess除了性能影响之外,这可能是您应该尽可能避免将重写规则放入文件的更好原因之一。如果将这些规则移至主服务器配置,则不会出现此问题,因为规则上的匹配不会触发内部子请求。如果您无权访问主服务器配置文件,则可以绕过它的一种方法(编辑:或者我认为,尽管它似乎不起作用 - 请参阅评论)是添加[NS](无子请求)标志到您的外部重定向规则,
RewriteRule ^index\.php$ http://example.com/index/%1/%2/? [L,R,NS]
Run Code Online (Sandbox Code Playgroud)
一旦你这样做了,你就不再需要检查REDIRECT_STATUS.
| 归档时间: |
|
| 查看次数: |
8960 次 |
| 最近记录: |