我尝试在apache配置文件中设置一些环境变量,并使用以下指令块给出标题" X-Forwarded-Proto"已经确定了。
<If "-n req('X-Forwarded-Proto')">
SetEnv NON_EMPTY_PROTO on
<If "req('X-Forwarded-Proto') =~ /https/">
SetEnv HTTPS on
</If>
<Else>
SetEnv HTTPS off
</Else>
</If>
因此,环境变量NON_EMPTY_PROTO按预期设置,但变量HTTPS不是。 但如果我为了测试而避免嵌套,则两个变量都按预期设置。
<If "-n req('X-Forwarded-Proto')">
SetEnv NON_EMPTY_PROTO on
</If>
<If "req('X-Forwarded-Proto') =~ /https/">
SetEnv HTTPS on
</If>
<Else>
SetEnv HTTPS off
</Else>
为什么在第一个例子中没有验证内部块?指令文档没有提到有关可能或不可能嵌套的任何内容。
顺便说一下,我知道我可以使用下面这样的逻辑等价物,但如果场景变得更复杂,嵌套会更简单,更方便。
<If "-n req('X-Forwarded-Proto') && req('X-Forwarded-Proto') =~ /https/">
SetEnv HTTPS on
</If>
<ElseIf "-n req('X-Forwarded-Proto')">
SetEnv HTTPS off
</ElseIf>
我明确地问这个嵌套版本在这里不起作用的原因。
答案 0 :(得分:3)
更新答案:
从Apache 2.4.26开始,允许使用嵌套的<If>
指令。
Apache 2.4 ChangeLog注意到以下更改:
评估嵌套的If / ElseIf / Else配置块。 [卢卡托斯卡诺,雅各布冠军]
问题中的嵌套<If>
指令应该适用于Apache 2.4.26和转发。
虽然我无法确认问题中的具体规则,但这是一个带有嵌套<If>
指令的htaccess规则的工作示例:
RewriteEngine On
<If "%{REQUEST_URI} =~ /flintstones$/ ">
<If "%{QUERY_STRING} == 'character=fred'">
ErrorDocument 200 "Fred says, \"Yabba Dabba Doo\" <a href=\"flintstones\">back</a>"
</If>
<ElseIf "%{QUERY_STRING} == 'character=barney'">
ErrorDocument 200 "Barney says, \"Uh hee hee hee... Okay Fred!\" <a href=\"flintstones\">back</a>"
</ElseIf>
<Else>
ErrorDocument 200 "Pick a Flintstones character: <a href=\"flintstones?character=fred\">Fred</a> or <a href=\"flintstones?character=barney\">Barney</a>"
</Else>
RewriteRule ^ - [R=200,L]
</If>
原始答案
<If>
指令不能嵌套在另一个<If>
指令中。
Apache 2.4 Documentation for the If Directive有以下声明:
不是脚本语言
该指令的名称对于程序员和管理员来说非常熟悉,但不应与脚本语言中的对应程序混淆。例如,当前的实现没有考虑在另一个内部使用
<If>
部分的可能性(内部<If>
将被忽略)。
没有理由为什么他们选择不允许嵌套的If指令。
文档中唯一的other information about nesting provided表示每个部分类型是否可以嵌套:
嵌套部分
某些节类型可以嵌套在其他节类型中。一方面,
<Files>
可以在<Directory>
内使用。另一方面,<If>
可以在<Directory>
,<Location>
和<Files>
部分内使用(但不能在另一个<If>
内部使用)。命名部分的正则表达式对应部分表现相同。