在 nginx 访问日志中记录包含点(句点)的 HTTP 标头

在 nginx 访问日志中记录包含点(句点)的 HTTP 标头

我有一个自定义标头“ AB.CD”。我想将此标头值记录在我的 nginx 访问日志中。

这是我想在 nginx.conf 中尝试的日志格式:

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" "$http_AB.CD" '

但是点(句号)似乎是不可接受的。我也尝试过将其转义,但没有用。它将数据记录为 ... "-" "-.CD"

记录其中包含点的标题的正确方法是什么?

答案1

尽管这一时期确实HTTP 标头的有效字符,看来 nginx 无法正确处理它。这不仅仅是将值记录到文件中。

在尝试记录此自定义标头之前,请确保该标头确实可供记录!在本例中,nginx 似乎不是将其识别为有效的标题。

尝试设置自定义标头并运行以下简单的 PHP 脚本(示例来自php.net):

<?php
foreach (getallheaders() as $name => $value) {
    echo "$name: $value<br/>\n";
}

这将显示请求中所有标头的可读列表。

现在,使用这些 Web 开发人员工具,我尝试设置带有句点的自定义 HTTP 标头:

每个工具的行为方式都相同:具有正常名称(如AB-CD)的 HTTP 标头按预期工作;名称为AB.CD或的 HTTP 标头AB%CD无法被 nginx 识别,并且不会显示在以上脚本的输出中。

以上内容适用于nginx-1.10.3nginx-1.11.8nginx-1.12.0nginx-1.13.1

答案2

escape尝试在日志格式中使用参数:

来自[nginx 文档]:1

The escape parameter (1.11.8) allows setting json or default
characters escaping in variables, by default, default escaping
is used.

答案3

文档固然很好,但最终的真相来源是源代码,通过这种方式甚至可能更容易找到您想要的东西。或者不是——YMMV。

函数ngx_http_log_compile_format()http://lxr.nginx.org/source/src/http/modules/ngx_http_log_module.c是解析你的指令的位log_format

1603               if ((ch >= 'A' && ch <= 'Z')
1604                         || (ch >= 'a' && ch <= 'z')
1605                         || (ch >= '0' && ch <= '9')
1606                         || ch == '_')
1607                     {
1608                         continue;
1609                     }
1610 
1611                     break;

所以这一点已经足够清楚了——log_format 指令中的变量名只能包含字母数字加“_”。

但这并不是故事的结束,因为还有一个问题:包含“。”的标题如何映射到变量名。

http://lxr.nginx.org/source/src/http/ngx_http_parse.c在 中进行解析 ngx_http_parse_header_line()。不过,要读的内容比我真正想读的要多一些。看来,如果代码在字段名称中遇到“。”,则不会对字段名称的哈希进行任何处理。 设置了,但在某些其他情况下r->invalid_header = 1;却没有设置。(参见代码行 922-982)。return NGX_HTTP_PARSE_INVALID_HEADER;

我不想继续通过代码探索到底有什么r->invalid_header = 1;用,而且这似乎也没有必要。log_format ... ${http_abcd} ...可能会起作用,如果不行,那么我怀疑什么都不会起作用。我只想尝试一下,如果不行,就假设什么都不会起作用。

相关内容