Apache 模块 mod_headers

Description:自定义 HTTP 请求和响应头
Status:Extension
Module Identifier:headers_module
Source File:mod_headers.c

Summary

该模块提供指令以控制和修改 HTTP 请求和响应 Headers。Headers 可以合并,替换或删除。

处理 Sequences

mod_headers提供的指令几乎可以在服务器配置中的任何位置出现,并且可以通过将其包含在configuration sections中来限制其范围。

处理的 Sequences 很重要,并且受配置文件中的 Sequences 和configuration sections中的位置的影响。如果相反,这两个指令具有不同的效果:

RequestHeader append MirrorID "mirror 12"
RequestHeader unset MirrorID

这样一来,就不会设置MirrorIDHeaders。如果反向,则将 MirrorID Headers 设置为“镜像 12”。

早期和晚期处理

mod_headers可以在请求的早期或晚期应用。正常模式已晚,在运行内容生成器之前立即设置了* Request Headers 和 Response *Headers 时,就像响应是通过网络发送的一样。始终在可运行的服务器中使用“后期”模式。

早期模式旨在为开发人员提供测试/调试帮助。使用early关键字定义的指令是在处理请求的开始时设置的。这意味着可以将它们用于模拟不同的请求并设置测试用例,但这也意味着可以在生成响应之前由其他模块随时更改 Headers。

由于早期指令是在遍历请求路径的配置之前处理的,因此只能在主服务器或虚拟主机上下文中设置早期 Headers。早期的指令不能依赖于请求路径,因此它们将在诸如<Directory><Location>的上下文中失败。

Examples

将所有以“ TS”开头的请求 Headers 复制到响应 Headers:

Header echo ^TS
  • 在响应中添加 HeadersMyHeader,其中包括时间戳,该时间戳表示接收请求的时间以及开始处理请求所需的时间。Client 端可以使用此 Headers 来指示服务器上的负载或隔离 Client 端和服务器之间的瓶颈。
Header set MyHeader "%D %t"

导致将此 Headers 添加到响应中:

MyHeader: D=3775428 t=991424704447256

向乔问好

Header set MyHeader "Hello Joe. It took %D microseconds for Apache to serve this request."

导致将此 Headers 添加到响应中:

MyHeader: Hello Joe. It took D=3775428 microseconds for Apache to serve this request.

  • 当且仅当 HeadersMyRequestHeader存在于请求中时,才有条件地在响应上发送MyHeader。这对于响应某些 Client 端刺激构建 Headers 很有用。请注意,此示例需要mod_setenvif模块的服务。
SetEnvIf MyRequestHeader myvalue HAVE_MyRequestHeader
Header set MyHeader "%D %t mytext" env=HAVE_MyRequestHeader

如果 HTTP 请求中存在 HeadersMyRequestHeader: myvalue,则响应将包含以下 Headers:

MyHeader: D=3775428 t=991424704447256 mytext

  • 通过在 Destination Headers 中将 https:替换为 http :,使 DAV 能够与通过 SSL 硬件(problem description)运行 HTTP 的 Apache 一起使用:
RequestHeader edit Destination ^https: http: early
  • 在多个非排他条件下设置相同的 Headers 值,但不要在最终 Headers 中重复该值。如果以下所有条件都适用于请求(即CGINO_CACHENO_STORE环境变量都存在于请求中):
Header merge Cache-Control no-cache env=CGI
Header merge Cache-Control no-cache env=NO_CACHE
Header merge Cache-Control no-store env=NO_STORE

那么响应将包含以下 Headers:

Cache-Control: no-cache, no-store

如果使用append而不是merge,则响应将包含以下 Headers:

Cache-Control: no-cache, no-cache, no-store

仅在 Client 未向我们发送 Cookie 的情况下设置测试 Cookie

Header set Set-Cookie testcookie "expr=-z %{req:Cookie}"

为 HTTP 状态码为 200 的响应附加一个缓存头

Header append Cache-Control s-maxage=600 "expr=%{REQUEST_STATUS} == 200"

Header Directive

Description:配置 HTTP 响应头
Syntax:Header [condition] add|append|echo|edit|edit*|merge|set|setifempty|unset|note header [[expr=]value [replacement] [early|env=[!]varname|expr=expression]]
Context:服务器配置,虚拟主机,目录,.htaccess
Override:FileInfo
Status:Extension
Module:mod_headers
Compatibility:SetIfEmpty 在 2.4.7 和更高版本中可用,expr = value 在 2.4.10 和更高版本中可用

该指令可以替换,合并或删除 HTTP 响应 Headers。在运行内容处理程序和输出过滤器之后立即修改 Headers,从而允许修改传出 Headers。

可选的 condition 参数确定此伪指令将针对哪个内部响应头表:onsuccess(默认,可以省略)或always。这两个列表之间的区别在于,即使在发生错误时,后者中包含的 Headers 也会添加到响应中,并在内部重定向(例如 ErrorDocument 处理程序)中保持不变。还请注意,在某些情况下,在两种情况下都重复此指令是有意义的,因为相对于现有 Headers,always不是onsuccess的超集:

  • 您正在向本地生成的非成功(非 2xx)响应(例如重定向)添加 Headers,在这种情况下,最终响应中仅使用与always对应的表。

  • 您正在修改或删除由 CGI 脚本或mod_proxy_fcgi生成的 Headers,在这种情况下,CGI 脚本的 Headers 在与always相对应的表中,而不在默认表中。

  • 您正在修改或删除由服务器的某些部分生成的 Headers,但是默认的onsuccess条件找不到该 Headers。

onsuccessalways之间的这种差异是由于 httpd 内部存储 HTTP 响应的 Headers 而导致的,因为它不提供任何“标准化”Headers 列表。如果在编写配置时不牢记以下概念,可能会出现的主要问题是某些 HTTP 响应可能最终会重复相同的 Headers(使用户困惑,有时甚至是 HTTP Client 端)。例如,假设您使用mod_proxy_fcgi进行了简单的 PHP 代理设置,并且后端 PHP 脚本将X-Foo: barHeaders 添加到每个 HTTP 响应中。如上所述,mod_proxy_fcgi使用always表存储 Headers,因此如下所示的配置最终导致错误的结果,即使 Headers 重复使用两个值:

# X-Foo's value is set in the 'onsuccess' headers table
Header set X-Foo: baz

为了规避此限制,可以使用一些已知的配置模式,例如:

# 'onsuccess' can be omitted since it is the default
Header onsuccess unset X-Foo
Header always set X-Foo "baz"

与上述条件参数不同,您可以基于 HTTP 状态代码来限制操作,例如代理或 CGI 请求。请参阅上面部分中使用%\ {}的示例。

它执行的操作由第一个参数(如果指定了条件,则由第二个参数)确定。这可以是以下值之一:

Warning

开始阅读操作列表之前,请先阅读上述alwaysonsuccessHeaders 列表之间的区别,因为该重要概念仍然适用。实际上,每个动作均按描述的方式工作,但仅在目标 Headers 列表上。

  • add

    • 即使该头已经存在,也会将响应头添加到现有的头集中。这可能导致两个(或多个)具有相同名称的 Headers。这可能会导致无法预料的后果,通常应使用setappendmerge代替。
  • append

    • 响应头被附加到任何同名的现有头上。将新值合并到现有 Headers 时,它将用逗号与现有 Headers 分开。这是给 Headers 提供多个值的 HTTP 标准方法。
  • echo

    • 具有此名称的请求 Headers 将在响应 Headers 中回显。Headers 可能是regular expression。值必须省略。
  • edit

  • edit*

    • 如果此响应 Headers 存在,则其值将根据regular expression搜索并转换。 value 参数是regular expression,替换项是替换字符串,其中可能包含反向引用或格式说明符。 edit表单将匹配并在 Headers 值中完全替换一次,而edit*表单将替换搜索模式的每个实例(如果出现多次)。
  • merge

    • 响应 Headers 会附加到任何同名的现有 Headers 中,除非要附加的值已经出现在 Headers 的逗号分隔值列表中。将新值合并到现有 Headers 时,它将用逗号与现有 Headers 分开。这是给 Headers 提供多个值的 HTTP 标准方法。在区分所有格式说明符之后,将以区分大小写的方式比较值。双引号中的值被认为不同于其他相同的未引号。
  • set

    • 设置了响应头,并使用该名称替换任何先前的头。该值可以是格式字符串。
  • setifempty

    • 设置了请求 Headers,但前提是之前没有使用该名称的 Headers。

Note

Content-Type Headers 是一种特殊的用例,因为在确定setifempty时,可能会确定其值,但 Headers 不是响应的一部分。在此用例中使用set更安全,如以下示例所示:

Header set Content-Type "text/plain" "expr=-z %{CONTENT_TYPE}"
  • unset

    • 该名称的响应头(如果存在)将被删除。如果有多个同名标题,则将全部删除。值必须省略。
  • note

    • 命名响应 Headers 的值被复制到内部笔记中,该笔记的名称由 value 指定。如果将 CGI 或代理资源发送的 Headers 配置为未设置但也应记录下来,则这很有用。
      在 2.4.7 及更高版本中可用。

此参数后跟标题名称,可以包含最后的冒号,但这不是必需的。忽略setappendmergeaddunsetedit的大小写。 echo的标题名称区分大小写,并且可以是regular expression

对于setappendmergeadd,将值指定为下一个参数。如果 value 包含空格,则应将双引号引起来。值可以是字符串,包含mod_headers特定格式说明符(和字符 Literals)的字符串或带有* expr = *前缀的ap_expr表达式

值支持以下格式说明符:

FormatDescription
%%百分号
%t自纪元(1970 年 1 月 1 日)以来的通用协调时间收到请求的时间,以微秒为单位。该值前面有t=
%D从接收到请求到在网络上发送头的时间。这是对请求持续时间的度量。该值前面有D=。该值以微秒为单位。
%l实际服务器本身的当前平均负载。它旨在公开由getloadavg()获得的值,它表示当前平均负载,5 分钟平均值和 15 分钟平均值。该值以l=开头,每个平均值以/分隔。<_ 150>在 2.4.4 及更高版本中可用。
%i基于可用进程和线程的 httpd 当前空闲百分比(0 到 100)。该值前面有i=。<_ 153>在 2.4.4 及更高版本中可用。
%b基于可用进程和线程的 httpd 当前繁忙百分比(0 到 100)。该值的前面是b=。<_ 156>在 2.4.4 及更高版本中可用。
%{VARNAME}eenvironment variable VARNAME的内容。
%{VARNAME}sSSL 环境变量 VARNAME的内容(如果启用了mod_ssl)。

Note

%s格式说明符仅在 Apache 2.1 及更高版本中可用;可以使用它代替%e来避免启用SSLOptions +StdEnvVars的开销。如果由于某种其他原因必须启用SSLOptions +StdEnvVars,则%e将比%s更有效。

Note on expression values

当 value 参数使用ap_expr解析器时,某些表达式语法将不同于评估* boolean *表达式的示例,例如:

  • 语法的起点是“字符串”而不是“ expr”。

  • 函数调用使用%\ {}语法而不是 funcname(arg)。

  • 从此起点当前无法使用多参数函数

引用整个参数,例如

Header set foo-checksum "expr=%{md5:foo}"

对于edit,既有一个值参数regular expression,又有一个附加的替换字符串。从版本 2.4.7 开始,替换字符串也可能包含格式说明符。

Header指令后可以跟一个附加参数,该参数可以是以下任意一个:

  • early

  • env=[!]varname

    • 仅当environment variable varname存在时,才应用该指令。 varname前面的!会反转测试,因此该指令仅在未设置varname时适用。
  • expr=expression

    • 当且仅当 expression 的计算结果为 true 时,才应用该指令。 ap_expr文档中记录了表达式语法和评估的详细信息。
# This delays the evaluation of the condition clause compared to <If>
Header always set CustomHeader my-value "expr=%{REQUEST_URI} =~ m#^/special_path.php$#"

除在early模式下外,在将响应发送到网络之前将处理Header伪指令。这意味着可以设置和/或覆盖大多数 Headers,但 HTTP Headers 过滤器添加的某些 Headers 除外。在 2.2.12 之前,无法使用此伪指令更改 Content-Type Headers。

RequestHeader Directive

Description:配置 HTTP 请求 Headers
Syntax:RequestHeader add|append|edit|edit*|merge|set|setifempty|unset header [[expr=]value [replacement] [early|env=[!]varname|expr=expression]]
Context:服务器配置,虚拟主机,目录,.htaccess
Override:FileInfo
Status:Extension
Module:mod_headers
Compatibility:SetIfEmpty 在 2.4.7 和更高版本中可用,expr = value 在 2.4.10 和更高版本中可用

该指令可以替换,合并,更改或删除 HTTP 请求 Headers。Headers 在内容处理程序运行之前被修改,允许传入的 Headers 被修改。它执行的操作由第一个参数确定。这可以是以下值之一:

  • add

    • 即使此 Headers 已经存在,请求 Headers 也会添加到现有的 Headers 集中。这可能导致两个(或多个)具有相同名称的 Headers。这可能会导致无法预料的后果,通常应使用setappendmerge代替。
  • append

    • 请求 Headers 将附加到任何现有的同名 Headers。将新值合并到现有 Headers 时,它将用逗号与现有 Headers 分开。这是给 Headers 提供多个值的 HTTP 标准方法。
  • edit

  • edit*

    • 如果此请求 Headers 存在,则其值将根据regular expression搜索并转换。 value 参数是regular expression,替换项是替换字符串,其中可能包含反向引用或格式说明符。 edit表单将匹配并在 Headers 值中完全替换一次,而edit*表单将替换搜索模式的每个实例(如果出现多次)。
  • merge

    • 除非要附加的值已经出现在现有 Headers 的逗号分隔值列表中,否则请求 Headers 将附加到任何同名的现有 Headers 中。将新值合并到现有 Headers 时,它将用逗号与现有 Headers 分开。这是给 Headers 提供多个值的 HTTP 标准方法。在区分所有格式说明符之后,将以区分大小写的方式比较值。双引号中的值被认为不同于其他相同的未引号。
  • set

    • 设置了请求 Headers,用该名称替换了以前的所有 Headers
  • setifempty

    • 设置了请求 Headers,但前提是之前没有使用该名称的 Headers。
      在 2.4.7 及更高版本中可用。
  • unset

    • 如果该名称的请求 Headers 存在,则将其删除。如果有多个同名标题,则将全部删除。值必须省略。

此参数后跟标题名称,可以包含最后的冒号,但这不是必需的。大小写被忽略。对于setappendmergeadd,给定值作为第三个参数。如果值包含空格,则应该用双引号将其引起来。对于unset,不应该给出任何值。值可以是字符串,包含格式说明符的字符串或两者的组合。支持的格式说明符与Header相同,请查看那里的详细信息。对于edit,值和替换项都是必需的,分别是regular expression和替换字符串。

RequestHeader指令后可以跟一个附加参数,该参数可以是以下任意一个:

  • early

  • env=[!]varname

    • 仅当environment variable varname存在时,才应用该指令。 varname前面的!会反转测试,因此该指令仅在未设置varname时适用。
  • expr=expression

    • 当且仅当 expression 的计算结果为 true 时,才应用该指令。 ap_expr文档中记录了表达式语法和评估的详细信息。

除了在early模式下之外,在修复阶段,RequestHeader伪指令在请求由其处理程序运行之前即被处理。这应该允许浏览器或 Apache Importing 过滤器生成的 Headers 被覆盖或修改。