httpd.conf 中的${var}
和有什么区别?%{var}
如何以及何时使用${}
and %{}
?
http://httpd.apache.org/docs/2.4/configuring.html提及:
使用 Define 或 shell 环境变量定义的变量值可以在配置文件行中使用语法 ${VAR}。
http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html提及:
服务器变量:这些变量的形式为 %{ NAME_OF_VARIABLE }
和
RewriteMap 扩展:这些是形式为 ${mapname:key|default} 的扩展。
将${VAR}
在 httpd.conf 中的任何地方使用,除了 mod_rewrite 指令(如 RewriteCond、RewriteRule,但除了使用 RewriteMap 扩展的除外,${}
如重写规则 ^/ex/(.*) ${examplemap:$1})
使用指令在 httpd.conf 中设置的变量SetEnvIf
,用于相同的 httpd.conf,是否可以用作${var}
除非当变量与 mod_rewrite 指令一起使用时,该变量将用作%{var}
?
答案1
httpd.conf 中的 ${var} 和 %{var} 有什么区别?
几乎所有事情。没有硬性规定说“$
做 x,%
做 y”,因为它们会根据使用地点和使用方式执行不同的操作。
${VAR} 是否会在 httpd.conf 中的任何地方使用,除了在 mod_rewrite 指令中
否 -${VAR}
用作替代每一个整个配置中的位置,甚至在与 mod_rewrite 相关的行中。这些只能在启动时使用-D
传递给 httpd 二进制文件的选项或Define
指令来定义。
之所以可以这样做,是因为这些变量不能包含字符:
,而RewriteMap
用法必须包含:
字符。这允许$
以完全不同的方式使用而不会发生冲突 - 解析器看到:
并知道它不应该替换那个。
使用 SetEnvIf 指令在 httpd.conf 中设置的变量,在同一个 httpd.conf 中使用,是否会被用作 ${var},除非当变量与 mod_rewrite 指令一起使用时,变量将被用作 %{var}?
-D
不。环境变量与通过或设置的变量不同Define
- 它们是完全独立的每个请求上下文(这些是您使用 设置的上下文SetEnvIf
),只有某些指令会使用。它们在支持的地方被特别提及 - 在 mod_rewrite 中它们是%{ENV:variable}
,在日志中它们是%{variable}e
,并且许多指令都有一个看起来像 的逻辑检查env=variable
。
所以,基本上,这是一个令人困惑的混乱局面 - 这是过去几十年网络服务器历史的见证。可能让您感到困惑的主要事情是,mod_rewrite 的语法不会以任何方式扩展到配置的任何其他部分;它们完全不同。从这一切中得出的要点是,没有一个管理“规则”来使所有这些都有意义 - 一个地方的 a和另一个地方的$
a 完全不同。$
一些方便的参考点:
- 如果您希望在 Apache 启动时静态设置变量,请在 Apache 启动时使用
Define
和替换一次。这在您想要执行诸如在开发和生产环境之间共享配置文件之类的操作时非常有用 - 但不要将其与from${VAR}
的使用混淆,后者始终包含。$
RewriteMap
:
- 如果您希望在特定请求中使用变量,那么环境变量就是您的目标 - 但您无法假设在与特定指令一起使用时将使用哪种语法来获取它们。您需要查看该指令的文档。
- 当 mod_rewrite 有问题时,抛开你认为你所了解的变量及其语法。它在 中有自己的一组变量
%{VAR}
,你可以使用 获取“正常”环境变量%{ENV:VAR}
,也可以使用 设置环境变量[E=VAR]
。
答案2
我查看了mod_rewrite的源代码,发现注释(do_expand函数)中有如下说明:
/* variable lookup */
else if (*p == '%') {
...
/* map lookup */
else { /* *p == '$' */
因此看起来,% 用于精确变量,而 $ 用于哈希表(“映射”)中的查找。此外,所有 mod_rewrite 扩展都完全独立于核心 - 整个扩展都在模块中完成。
我之前曾想过,但那是错误的:
${} 变量用于项目的使用环境,并在配置解析时进行评估。
%{} 变量使用请求的环境,并在解析请求时进行评估。mod_rewrite 使用 %{} symmantic 来防止 httpd 核心进行配置时插值。