Apache HTTPD RewriteRule 中的 ^ 和 $ 是啥意思?

Posted

技术标签:

【中文标题】Apache HTTPD RewriteRule 中的 ^ 和 $ 是啥意思?【英文标题】:What is the meaning of ^ and $ in Apache HTTPD RewriteRule?Apache HTTPD RewriteRule 中的 ^ 和 $ 是什么意思? 【发布时间】:2020-04-12 11:14:33 【问题描述】:

我已成功将以下代码添加到我的 Apache HTTPD 配置中:

# Force www.
RewriteCond %HTTP_HOST !^www\.
RewriteRule ^(.*)$ https://www.%HTTP_HOST/$1 [R=301,L]
# Force https (SSL)
RewriteCond %HTTPS off
RewriteRule (.*) https://%HTTP_HOST%REQUEST_URI [R=301,L]

虽然它按预期工作,但我有一个理论上的问题:

为什么在第 3 行有一个 ^$ 强制执行“www.”,而不是在第 6 行强制执行“https”?

此致,多维德。

【问题讨论】:

【参考方案1】:

对于您的两个正则表达式模式^(.*)$(.*) 将表现相同。但是你猜怎么着,你不需要使用它们中的任何一个。事实上,不使用.* 并使用匹配完整URI 的%REQUEST_URI 变量(不是像.* 这样的相对变量)也不容易出错。所以我建议把你的规则改成这样:

# Force www.
RewriteCond %HTTP_HOST !^www\. [NC]
RewriteRule ^ https://www.%HTTP_HOST%REQUEST_URI [R=301,L,NE]

# Force https (SSL)
RewriteCond %HTTPS off
RewriteRule ^ https://%HTTP_HOST%REQUEST_URI [R=301,L,NE]
标志NE 用于不转义。如果您的原始 URI 包含一些特殊字符,例如 #(,),[,] 等,则使用此标志很有用。 上面RewriteRule 模式中的^ 什么都不做,只会为每个匹配项返回true,因为^ 表示字符串的开始位置,它将始终匹配。 这两个规则可以组合成一个规则,但看起来有点复杂。

这里是:

RewriteCond %HTTP_HOST !^www\. [NC,OR]
RewriteCond %HTTPS !on
RewriteCond %HTTP_HOST ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%REQUEST_URI [R=301,L,NE]

下面是这条规则的解释:

RewriteCond %HTTP_HOST !^www\. [NC,OR]: 如果HOST_NAME 不以www. 开头 [NC,OR]:忽略大小写匹配和ORs 下一个条件 RewriteCond %HTTPS !onHTTPS 未开启 RewriteCond %HTTP_HOST ^(?:www\.)?(.+)$ [NC]:此条件将始终匹配,因为 www. 在此处是可选匹配。它用于捕获HTTP_HOST 的子字符串,而无需在捕获组#1 中使用(.+) 模式启动www.(稍后将反向引用为%1)。请注意,(?:..) 是非捕获组。 RewriteRule ^ https://www.%1%REQUEST_URI [R=301,L,NE]^ 将始终匹配。通过将https://www. 添加到%1,此规则将重定向到带有R=301 代码的https://www.%1%REQUEST_URI%1 是来自RewriteCond 的捕获组#1 的反向引用,如上所述。

【讨论】:

【参考方案2】:

如果使用 Apache 的模块 mod_rewrite,那么您可以定义一个 RewriteRule。

RewriteRule 使用正则表达式

关键字或指令 RewriteRule 后跟 Regular Expression(也称为 RegExpattern)。此 RegEx(例如 ^(.*)$)用于匹配输入 URL 以便重写它们。

正则表达式使用特殊字符编码

RegEx 模式中,^ 标记要匹配的行的开头,而结尾由 $ 表示。

两者都称为元字符并具有特殊含义:

^:匹配字符串中的起始位置。在基于行的工具中,它匹配任何行的起始位置。

$:匹配字符串的结束位置或字符串结束换行符之前的位置。在基于行的工具中,它匹配任何行的结束位置。

为什么它们经常过时?

由于到达 HTTP 服务器的 URL 总是由一行表示,这些 行分隔 元字符也可以省略而不影响模式/重写规则。

【讨论】:

B"H 你好 hc_dev 我现在明白为什么在这种情况下没有区别,谢谢你。真诚的,Dovid。【参考方案3】:

它们是一样的。 ^(.*)$(.*) 没有区别。

.* 匹配任何字符串。 ^$ 不要更改它,因为所有字符串都有开始和结束。

【讨论】:

B"H 感谢匿名者的回复。在任何文档中都提到过吗?此致,Dovid。 @Dovid 这些是正则表达式控制字符。 ^ 表示“字符串的开头”。 $ 表示“字符串结束”。在这种特定的情况下,它们具有相同的含义。在其他情况下,它们可能很重要。 @Dovid 否,但httpd.apache.org/docs/current/rewrite/intro.html 上有一些示例显示.* 匹配所有内容。 ^$ 不要改变它。 B"H 再次感谢匿名用户的额外回复。此致,Dovid。 不要做那种不加解释就...简洁地回答的人;-)【参考方案4】:

这取决于您是否为不带 www 或带 www 的域制作了证书。

在提供的示例中,重定向(第 6 行)是对域 没有 www。这样可以保证提供正确的证书,并且浏览器在访问您的网站时不会显示警报。

【讨论】:

B"H 感谢 Skatox 的回复。如果没有“www.”,则代码的前半部分(第 3 行)会同时添加“www.”和“https”。如果“www.”已经存在,那么第 6 行中“HTTP_HOST”的那部分不是吗?因为如果不是,那么地址将保留没有“www.”,而实际上是“www.”。总是添加。我必须承认,我不知道如何检查两者中的哪一个,www。或非 www.,有我的 Hostgator 提供商颁发给它的证书。甚至不知道这有什么不同。此致,多维德。 HTTP_HOST 只是域,没有别的。如果我的回答帮助您记得将其标记为已解决并投票:)

以上是关于Apache HTTPD RewriteRule 中的 ^ 和 $ 是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

apache rewrite功能

Apache 在 htaccess 禁止访问 和 conf 中的 禁止访问 区别

如何验证apache 允许OPTIONS方法

如何在 Apache 中配置 Vue 路由器历史模式

怎么用apache绑定2级域名?

Apache通过rewrite限制某个目录---模块