我可以使用嵌套Apache 2.4 中 .htaccess 中的指令

我可以使用嵌套Apache 2.4 中 .htaccess 中的指令

我正在尝试使用 .htaccess 文件中的 Redirect 和 RedirectMatch 规则模拟我网站先前版本的永久链接结构。

我有不同的规则,我想将这些规则应用于旧网站的不同路径。有些目录没有类似规则,我希望它们重定向到一个位置。有些目录包含许多项目(数千个),位于不同的位置,我希望它们能够巧妙地重定向到新网站中正确的新位置。

看来我可以使用 <If> 上的基本正则表达式测试来保护和分组相关项目,以防止所有包含的分组重定向在它们永远不匹配的情况下被测试。在这种方法中,生成的配置看起来合乎逻辑且连贯,并且可以轻松自动生成:

<If "%{REQUEST_URI} =~ m#^/categories/software/.*#">
    # These rules aren't considered if the request wasn't for a subpath of categories/software.

    <If "%{REQUEST_URI} =~ m#^/categories/software/store/.*#">
        # All old store pages now invalid, go to main store.    
        RedirectMatch 301 .* /software-store/
    </If>

    # Regexes for each category of software to group them logically.
    # And so that 1,000s of redirects don't get considered on each page load.
    <If "%{REQUEST_URI} =~ m#^/categories/software/item/.*#">
        # Loads and loads of redirect lines for pages with arbitrary rules to product pages.
        Redirect 301 "/categories/software/item/foo" /software-store/games/foo
        Redirect 301 "/categories/software/item/bar" /software-store/productivity/bar
        Redirect 301 "/categories/software/item/baz" /software-store/misc/baz
        # ...
    </If>
    <If "%{REQUEST_URI} =~ m#^/categories/software/dlc/.*#">
        # Loads and loads of redirect lines. It could also be grouped into subdirectories of dlc/ and so on.
        # ...
    </If>
</If>
# ...

对于庞大的目录,一些保护正则表达式可以防止数千个无用的测试。

我使用的是 Apache 2.4,其中可以使用 <If> 指令,但上述指令没有达到我预期的效果。内部的 <If> 被完全忽略。

如果我删除封闭的 <If> 并只显示最内层的 <If>,规则就会起作用,所以我不认为我的语法或重定向规则有问题。

我怀疑问题在于我无法嵌套 <If>,尽管这似乎是一件很常见的事情。在文档中,我看不到任何关于嵌套的参考,无论是允许的还是其他的。 http://httpd.apache.org/docs/2.4/mod/core.html#if

我可以嵌套 <If> 指令吗?如果是这样/如果不是,您能否指出文档中说明原因的部分?

答案1

更新答案:

从 Apache 2.4.26 开始<If>允许嵌套指令。

更改日志已注意到以下变化:

评估嵌套的 If/ElseIf/Else 配置块。[Luca Toscano、Jacob Champion]


原始答案:

指令<If>不能嵌套在另一个指令中,<If>但可以嵌套在其他部分中,例如<Directory><Location>和。<Files><IfModule>

Apache 2.4 If 指令文档有以下通知:

不是脚本语言

程序员和管理员对这个指令的名称非常熟悉,但不要将其与脚本语言中的对应指令混淆。例如,当前实现不考虑将一个<If>部分放在另一个部分中的可能性(内部部分<If>将被忽略)。

他们没有给出为什么选择不允许嵌套<If>指令的理由。

唯一的提供有关嵌套的其他信息在文档中指出每个部分类型在是否可以嵌套方面有所不同:

节的嵌套

某些节类型可以嵌套在其他节类型中。一方面,<Files>可以在 内使用<Directory>。另一方面,<If>可以在<Directory><Location><Files>节内使用(但不能在另一个 内使用<If>)。命名节的正则表达式对应项的行为相同。

答案2

Apache 不一定“按顺序”读取配置,而是会经历一个相当复杂的合并过程。因此,最佳“匹配”有时很难预测,而且几乎总是需要考虑出现在所有不同配置部分中的指令。

您可以查看配置部分的文档,特别注意如何合并各部分以便更好地理解这一点。

另请注意,添加以下指令可能会获得更好的结果<其他><ElseIf>

相关内容