抱歉,如果之前已经问过/回答过这个问题,但我无法找到这个特定问题的答案。
如果我创建一个带有简单重写规则的 .htaccess 文件,该规则就会起作用。如果我在子目录中创建另一个带有其自身重写配置的 .htaccess 文件,则顶层的主 .htaccess 文件将停止读取。我甚至不需要创建任何规则。只需在子目录中打开重写引擎,更高级别的重写就会停止工作。
我创建了一组包含两个文本文件的子目录:
[root@apachetest html]# cat test/1/test.txt
1
[root@apachetest html]# cat test/2/test.txt
2
还有一个 .htaccess 文件,用于将 test/1/test.txt 重写为 test/2/test.txt
[root@apachetest html]# cat test/.htaccess
RewriteEngine on
RewriteRule 1/test.txt 2/test.txt [L]
这按预期工作。如果我请求 1/test.txt,我会得到 2/test.txt
[root@apachetest html]# curl localhost/test/1/test.txt
2
但是,如果我在 test/1/ 子目录中创建另一个 .htaccess 文件,那么 test/.htaccess 文件将停止工作。
[root@apachetest html]# echo "RewriteEngine On" > test/1/.htaccess
[root@apachetest html]# curl localhost/test/1/test.txt
1
我已经尝试了 /test/.htaccess 和 /test/1/.htaccess 中的所有 RewriteOptions、Inherit、InheritBefore、InheritDown、InheritDownBefore 和 IgnoreInherit,但是如果 /test/1/.htaccess 中有任何重写配置,我就无法使 /test/.htaccess RewriteRule 正常工作。
我需要能够将 RewriteRules 放在子目录中,而不会影响顶级目录中的 RewriteRules。有人能告诉我我遗漏了什么吗?
答案1
是的,默认情况下,mod_rewrite 指令不会被子配置继承。因此,如果您在子目录.htaccess
文件中有 mod_rewrite 指令(即使只是启用或禁用重写引擎),那么父目录/配置中的 mod_rewrite 指令将被完全覆盖 - 它们根本不会被处理。
我已经尝试了所有的 RewriteOptions;Inherit、InheritBefore、InheritDown、InheritDownBefore……
是的,这就是启用 mod_rewrite 继承所需要做的事情。选择哪个选项取决于您希望在何处以及何时继承父/子指令。
然而,“问题”在于 mod_rewrite 指令的“继承”方式。它们是通过将指令有效地复制到相应的配置中来继承的。它们不会在其原始配置的上下文中处理。这会影响相对 URL 路径之类的内容。通常,指令RewriteRule
会匹配相对于包含该文件的目录的 URL 路径.htaccess
。但是,如果这些指令被“继承”(即有效地复制)到子配置中,那么这些相对 URL 路径将会有所不同,并且规则可能不再匹配。
“继承”指令需要以这样一种方式编写,即它们不依赖于处理它们的目录 - 因此您不一定依赖于RewriteRule
图案在继承指令时目录语境。
因此,用你的例子...
# test/.htaccess RewriteEngine on RewriteRule 1/test.txt 2/test.txt [L]
/test/1
并且我们在子目录文件中启用mod_rewrite继承.htaccess
:
# test/1/.htaccess
RewriteEngine on
RewriteOptions Inherit
这实际上会导致请求时处理以下内容/test/1/test.txt
:
# test/1/.htaccess
RewriteEngine on
RewriteOptions Inherit
# Due to "Inherit" option the inherited directives from the parent config
# are effectively copied in-place after the existing directives...
RewriteRule 1/test.txt 2/test.txt [L]
显然,RewriteRule
图案 1/test.txt
文件中的test/1/.htaccess
永远不会匹配,因此规则不执行任何操作。(规则需要修改才能匹配test.txt
,但代换也需要修改,否则它会将请求重写为/test/1/2/test.txt
- 但这并不存在。)
需要修改继承/父级配置中的指令,以避免对父级所在目录的依赖.htaccess
。例如:
# test/.htaccess
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/([^/]+)/1/test\.txt$
RewriteRule (^|/)test\.txt$ /%1/2/test.txt [L]
这状况有效地重复了 的测试test.txt
,但更具体。你可以制作RewriteRule
图案完全通用,但规则将针对每个请求进行处理。
注意:我捕获了第一个路径段,并%1
在代换以避免必须对文件所在的目录进行硬编码.htaccess
。
当 mod_rewrite 用于以下情况时,这种“继承”模式会更加成问题/复杂:目录(.htaccess
)上下文。 (mod_rewrite 在用于目录上下文。)相对路径问题不是服务器配置/虚拟主机中的指令的问题,因为路径都是相对于根的。