在 apache 的 mod_rewrite 模块中,[l] 和 [end] 标志都用于停止处理后续的 rewriterule,但作用范围不同。[l] 仅停止当前一轮请求处理中的规则匹配,如果重写后的 url 再次触发内部子请求(如通过 r 重定向后重新进入循环),规则会从头开始执行;而 [end] 则立即终止所有后续的处理过程,包括后续的 rewrite 阶段、回调以及任何内部重定向,直接返回结果给客户端或下一阶段。
![Apache 中 RewriteRule 怎么配置 [END] 与 [L] 标志在重写中的区别](https://img.php.cn/upload/article/001/242/473/179469939955868.png)
[L] 标志在循环重定向中的行为表现是什么
[L] 标志的作用是“Last”,它告诉 Apache 停止处理当前这一轮请求中的剩余 RewriteRule,并将控制权交给下一个处理阶段或重新评估重写后的 URL。如果重写的目标 URL 仍然符合虚拟主机或目录上下文中的其他规则,Apache 可能会再次进入重写引擎进行处理,从而形成循环。这在配置外部重定向(R=301 或 R=302)时尤为常见,因为浏览器收到重定向响应后,会发起一个新的请求,这个新请求会再次经过 Apache 的规则集,如果规则未正确排除已重定向的路径,就会陷入死循环。
![Apache 中 RewriteRule 怎么配置 [END] 与 [L] 标志在重写中的区别](https://img.php.cn/upload/article/001/242/473/179469939998394.png)
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
RewriteEngine On
# 示例:将非 HTTPS 流量重定向到 HTTPS
# 使用 [L] 标志
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# 假设后续还有针对特定路径的内部重写
RewriteRule ^api/(.*)$ /backend/api.php?path=$1 [QSA,L]
</VirtualHost>在上述配置中,当用户访问 http://example.com/page 时,由于 %{HTTPS} 为 off,第一条规则匹配。Apache 应用 [L] 标志,停止处理该请求当前的规则列表,并生成一个 301 重定向响应,Location 头指向 https://example.com/page。浏览器接收到此响应后,会发起一个新的 GET 请求到 https://example.com/page。在这个新的请求中,Apache 再次加载配置文件,%{HTTPS} 现在为 on,第一条规则不匹配,因此跳过,继续处理第二条规则。如果第二条规则也匹配,则进行内部重写。关键在于,[L] 只影响当前请求实例的规则链,不影响新请求的规则链。如果配置不当,例如没有检查 %{HTTPS} 状态,而是简单地重写到自身且不加条件判断,[L] 无法阻止新请求再次触发规则。
[END] 标志如何彻底阻断重写引擎的后续处理
[END] 标志是 Apache 2.4 引入的功能,它比 [L] 更严格。当遇到 [END] 时,Apache 不仅停止处理当前的 RewriteRule 列表,还会立即终止整个请求处理过程中的所有后续重写阶段。这意味着,即使重写后的 URL 触发了新的内部子请求,或者进入了不同的处理阶段(如 post-read-request, pre-map-uri 等),只要之前有规则使用了 [END],就不会再有任何 mod_rewrite 规则被执行。这有效地防止了由重写引起的无限循环,并确保性能开销最小化,因为它避免了不必要的规则评估。
通过Apache Tika Server REST API从1400多种文件格式中提取文本和元数据。处理PDF、DOCX、PPTX、电子邮件归档以及带有MIME类型检测的嵌入式文档提取。
![Apache 中 RewriteRule 怎么配置 [END] 与 [L] 标志在重写中的区别](https://img.php.cn/upload/article/001/242/473/179469939955748.png)
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
RewriteEngine On
# 示例:将非 HTTPS 流量重定向到 HTTPS
# 使用 [END] 标志
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [END,R=301]
# 即使这里有更多规则,也不会被处理
RewriteRule ^api/(.*)$ /backend/api.php?path=$1 [QSA,L]
</VirtualHost>在与 [L] 相同的场景下,使用 [END] 标志的行为略有不同。当用户访问 http://example.com/page 时,第一条规则匹配,Apache 应用 [END] 标志。此时,Apache 立即终止所有后续的 mod_rewrite 处理,并生成 301 重定向响应。与 [L] 不同的是,[END] 确保在当前请求的生命周期内,没有任何其他 RewriteRule 会被考虑。更重要的是,在某些复杂的配置中,如果重写操作导致了内部子请求(例如通过 ProxyPass 或 Satisfy 指令引发的内部重定向),[END] 会阻止这些子请求再次触发重写规则。虽然在这个简单的 HTTPS 重定向例子中,[L] 和 [END] 的效果看似相似,因为它们都触发了外部重定向,但在更复杂的重写逻辑中,[END] 提供了更强的控制力,确保一旦满足条件,就不再有任何进一步的规则评估发生。
当重写规则包含 [R] 标志时,[END] 与 [L] 对后续内部重定向的影响有何不同
当重写规则中包含 [R](重定向)标志时,Apache 会向客户端发送一个 HTTP 重定向响应,客户端随后会发起一个新的请求。在这种情况下,[L] 和 [END] 的区别主要体现在新请求的处理上。对于 [L],新请求会重新经过所有的 RewriteRule,如果规则设计不当,可能导致循环。对于 [END],虽然它主要作用于当前请求的处理链,但由于它终止了所有后续处理,包括可能触发的内部子请求,因此在某些高级场景中,它能更有效地防止意外的规则匹配。然而,需要注意的是,[END] 并不阻止客户端发起的新请求,它只是确保在当前请求的处理过程中,一旦遇到 [END],就不会再有其他规则被评估。如果希望在新请求中也避免规则匹配,需要在规则中加入适当的条件,如 %{ENV:REDIRECT_STATUS} 来检测是否为重定向后的请求。
# 更安全的重定向配置,结合 [END] 和条件检查
RewriteEngine On
# 检查是否已经过重定向,避免循环
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [END,R=301]
# 后续规则
RewriteRule ^api/(.*)$ /backend/api.php?path=$1 [QSA,L]在这个改进的配置中,%{ENV:REDIRECT_STATUS} 是一个环境变量,当 Apache 处理内部重定向时,它会设置这个变量。通过检查它是否为空,可以确保只有在首次请求时才执行重定向。结合 [END] 标志,这不仅停止了当前请求的规则处理,还通过条件检查确保了新请求不会意外地再次触发重定向规则,除非明确需要。这种组合使用 [END] 和条件检查的方法,在处理复杂的 URL 重写和重定向逻辑时,提供了更高的安全性和可控性。

















