没有使用 [L] 标志的一系列 RewriteRule

3

更新: 今天我有点弄清楚了问题所在:现在看一下较小版本。

RewriteCond %{REQUEST_FILENAME} (.+)
RewriteRule first /landingpage1.php [R,ENV=lang:hi]

RewriteCond %{REQUEST_FILENAME} (.+)
RewriteRule second /landingpage2.php?id=%1&%{ENV:lang} [R,L]

我的htaccess文件位于/www/h/文件夹中。如果我输入localhost/h/firstsecond,它会返回localhost/landingpage1.php,但第4行的模式不符合要求。但是,如果我输入localhost/h/first/second,问题就出现了,它会落在localhost/landingpage2.php?id=localhost/landingpage1.php&hi上。实际上,在实验中有一次,我不知道如何做到的,发现使用localhost/h/first/second url时,它会重新定向到第一条rewriterule行的某些内容,例如localhost/landingpage1.php//second,并且当然这样我们就看到第二行有效了。我也看到过Alias "redirect"的这种行为,如果您的url中有一个文件夹路径,它会将剩余部分加入到最终重定向的url中,以及查询字符串。
因此,当localhost/h/firstsecond正常工作时,但localhost/h/first/second不正常工作时,我知道可能接近知道发生了什么。
归档:
我正在尝试理解没有Last标志的一堆rewriterule规则的行为。考虑我的htaccess文件位置是localhost/h/(Applications/AMPPS/www/h)。
示例1:
RewriteRule anchor/(.+) /hello [R,ENV=lang:hi]
RewriteRule anchor /anchor/guess [R]
RewriteRule /hello /yes [R]

如果我输入 localhost/h/anchor/text,那么我认为会发生以下情况:
  1. 第一行 RewriteRule anchor/(.+) /hello [R,ENV=lang:hi] 的模式 "anchor/(.+)" 匹配,因此它重定向到 localhost/hello,但由于没有 L 标志,重定向到 localhost/hello 被暂停,因此它继续执行以下内容

  2. 第二行的模式 "anchor" 与新的 http://localhost/hello 不匹配,因此被跳过

  3. 第三行的模式 /hello 与 localhost/hello 匹配,最终重定向到 localhost/yes
事情似乎按照我的想法进行,直到我看到下面的示例2:
RewriteRule foo/bar /tmp1/ [R]
RewriteRule foo/bar /tmp2/ [R]
RewriteRule (.+) /tmp3/ [R]
RewriteRule (.+) /tmp4/ [R]
RewriteRule hello /tmp6/ [R]
RewriteRule bar /tmp7/ [R]
RewriteRule hello /tmp8/ [R]
RewriteRule tmp7/ /tmp5/ [R]

同一位置的 htaccess 文件,我点击了 url localhost/h/foo/bar, 我认为会发生以下情况: 1. 第一行的模式“foo/bar”与url匹配,因此它重定向到http://localhost/tmp1/,但由于没有 L 标记,它被暂停了,继续执行下面的步骤。
2. 第二行的模式“foo/bar”与http://localhost/tmp1/不匹配,因此它被跳过,(如果我仅保留前两行,则最终重定向到http://localhost/tmp1/)。
3. 第三行的模式与 http://localhost/tmp1/ 匹配并重定向到 http://localhost/tmp3/。
4. 第四行的模式匹配,重定向到 http://localhost/tmp4/。
5. 第五行的“hello”不匹配,重定向地址仍然是 http://localhost/tmp4/。
6. 现在让我困惑了3个小时的是第六行的“bar”匹配,并重定向到http://localhost/tmp7/(删除最后两行以确认),究竟是怎么回事?
7. 第七行如预期所述不匹配。
8. 第八行的 tmp7/ 与 http://localhost/tmp7/ 匹配,最终重定向到 http://localhost/tmp5/。
现在问题是为什么第6行中的“bar”匹配,如果它可以与最早输入的 url(http://localhost/foo/bar)匹配,那么为什么它在相同例子的第二行中没有匹配,并且为什么它在示例1的第二行中没有匹配?
请注意,所有目标模式都指向文件夹外部(在上级、www 中),因此它们不会再次返回到 htaccess 文件。
2个回答

2

首先是一个非常好的问题,有很多细节。

如果您启用RewriteLog,您会注意到实际上是由这行代码引起的(当您请求http://localhost/h/first/second URL时):

add path info postfix: /landingpage1.php/second

这个问题在Apache官网上有一个专门的bug报告。

如果你在RewriteRule中省略了LDPI(即Discard Path Info标志,就会出现这种情况。

如果你使用以下代码,则会正常运行:

RewriteCond %{REQUEST_FILENAME} (.+)
RewriteRule first /landingpage1.php [R,DPI,ENV=lang:hi]

RewriteCond %{REQUEST_FILENAME} (.+)
RewriteRule second /landingpage2.php?id=%1&%{ENV:lang} [R,L]

1
太棒了,我之前不知道有DPI标志。现在它像魔法一样运行良好。 - Amit Bravo
我发现 mod Alias 的重定向也有类似的情况,既然我们没有在“redirect”中使用任何标志,那么它是正常的默认东西吗? - Amit Bravo
你也能用RedirectMatch进行测试吗? - anubhava

0
  1. 第一行的模式“foo/bar”与URL匹配,因此它重定向到http://localhost/tmp1/,但由于没有L,它被暂停,它会继续执行以下操作

不,这不是它的工作原理,因为有[R]标志,它发出重定向。重定向开始一个新的请求/响应周期,并且任何RewriteRules都将从头开始。无论是否使用[L]标志,都会发生相同的事情。


1
但如果它发出重定向,则应该首先发出类似于http://localhost/tmp1的第一个重定向,而且由于我的htaccess文件不在根文件夹(或Application/AMPPS/www),而是位于Application/AMPPS/www/h中,所以在这种情况下,我想它不应该再次命中htaccess文件。你的意见是什么? - Amit Bravo
1
如果我同意您的观点,即无论L标志如何,每当它看到[R]时都会发出重定向,那么按照相同的逻辑,我不明白为什么它满足第7行“RewriteRule bar /tmp7/ [R]”。 - Amit Bravo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接