我一直在为一个客户端提供一些重定向,他们需要在www.example.com上进行重定向domain.com以获得领先的www,而在sub.another.com上进行别名domain.com获得领先的www。我找到了一个solution,它可以工作。
我的前辈告诉我,只关心比赛(例如。RewriteRule ^
部分)在.htaccess中不起作用,显然只在virtualhost中起作用。我知道这两者之间有一些细微的区别,但我找不到任何来源(他也无法提供)说^
match在. htaccess中不起作用。
正确的规则应该是RewriteRule ^(.*) https://sub.another.com/$1 [R=301,L]
。有谁能解释一下为什么在.htaccess中匹配不起作用?如果互联网是可信的,^
和^(.*)
都应该匹配整条线。后者显式地告诉匹配行开头之后的任何内容,而前者匹配行开头本身(所以也应该匹配一个空字符串,参见this answer)。
1条答案
按热度按时间xzabzqsa1#
我的前辈告诉我,只关心比赛(例如。
RewriteRule ^
部分)在.htaccess
中不起作用,显然只在virtualhost中起作用这是无稽之谈。
^
(regex语法)简单地Assert字符串的开头。仅此而已因此,如果参数接受正则表达式(无论上下文如何),^
总是“工作”,这取决于您试图匹配的内容。(我想知道你是否真的指URL路径上的斜杠前缀?)显然只在virtualhost中
你可以说事实正好相反。
^$
将在.htaccess
中匹配,但在虚拟主机上下文中不匹配。(这与.htaccess
上下文中的根目录/ homepage匹配。)这仅仅是由于在这些不同的“上下文”中匹配的内容。(Apache配置中有4个上下文:
.htaccess
、directory、virtualhost 和 server。)在 virtualhost 上下文中,
RewriteRule
pattern 匹配完整的根相对URL路径,以斜线开始。因此,您需要匹配^/$
而不是^$
(以匹配根目录)。而在
.htaccess
(和 directory)上下文中,匹配的URL路径相对于包含.htaccess
文件的目录(目录前缀已被删除),因此不是以斜杠开头。例如,给定URL
https://example.com/foo/bar/baz
…RewriteRule
* 模式 * 与URL路径/foo/bar/baz
(以斜杠开头的完整URL路径)匹配。.htaccess
中,RewriteRule
pattern 与foo/bar/baz
匹配(无斜杠前缀)。但如果.htaccess
文件位于/foo
子目录(而不是根目录),则匹配的URL路径为:仅bar/baz
(省略/foo
)。正确的规则应该是
RewriteRule ^(.*) https://sub.another.com/$1 [R=301,L]
。谁能解释一下为什么匹配在.htaccess
中不起作用?这doeswork in
.htaccess
.事实上,这只适用于.htaccess
,因为如果你在 virtualhost 上下文中使用这个规则,那么你将在重定向请求的URL路径开始处使用双斜杠。(当然,其他规则可能会影响这种行为,.htaccess
文件的位置-如果在子目录中-也会改变这种行为。如果互联网是可信的,
^
和^(.*)
都应该匹配整条线。^
本身并不匹配任何东西,它只是Assert字符串的开头,所以总是“成功”。而^(.*)
Assert字符串的开头,然后匹配URL路径的其余部分,并在反向引用中捕获。事实上,^(.*)
中的^
前缀完全是可选的(当匹配URL路径时),因为regex是 greedy。^(.*)
和(.*)
是“相同的”。因为你在 substitution 字符串中使用了一个
$1
反向引用,所以你需要实际捕获一些东西,所以你需要(.*)
(因为^
不匹配/捕获任何东西,它只是一个 * Assert *)。但这是相同的,无论你在哪里使用这个指令:.htaccess
或 virtualhost。在这个特定规则中,您可以只使用
^
,而在 substitution 字符串中使用REQUEST_URI
服务器变量。例如:请注意,
REQUEST_URI
变量包含了整个URL路径,包括斜杠前缀,因此在 substitution 字符串中省略了斜杠。这个规则可以说比使用反向引用(上面的规则)“更好”,因为它在任何地方(任何目录)都可以工作,不考虑上下文,并且使用了更有效的正则表达式。