我有一个自定义标头“ 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 标头:
- 修改标头值 (HTTP 标头) 0.1.3 (火狐)
- 修改标头 0.7.1.1.1-signed.1-signed (火狐)
- HTTP 标头管理器 1.1.2 (火狐)
- 高级 REST 客户端 9.14.64.305-稳定版 (铬合金)
每个工具的行为方式都相同:具有正常名称(如AB-CD
)的 HTTP 标头按预期工作;名称为AB.CD
或的 HTTP 标头AB%CD
无法被 nginx 识别,并且不会显示在以上脚本的输出中。
以上内容适用于nginx-1.10.3
、nginx-1.11.8
、nginx-1.12.0
和nginx-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} ...
可能会起作用,如果不行,那么我怀疑什么都不会起作用。我只想尝试一下,如果不行,就假设什么都不会起作用。