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

我有一个自定义标题“ AB.CD ”。 我想在我的nginx访问日志中logging这个标题值。

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

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

然而点(周期)似乎是不可接受的。 我也尝试逃脱它,但没用。 它将数据logging为... "-" "-.CD"

logging一个包含点的标题的正确方法是什么?

虽然这段时间对于HTTP头来说确实是一个有效的字符 ,但看起来nginx并不能正确处理它。 这不仅仅是将该值logging到文件中。

在尝试logging这个自定义标题之前,确保标题实际上是可以被logging的! 在这种情况下,看起来nginx并不认为这是一个有效的头。

尝试设置自定义标题,并使用以下( php.net中的示例)运行这个简单的PHP脚本:

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

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

现在,使用这些Web开发人员工具,我试图设置一个自定义HTTP标头,

  • 修改标题值(HTTP Headers)0.1.3 (Firefox)
  • 修改头文件0.7.1.1.1-signed.1-signed (Firefox)
  • HTTP标题pipe理器1.1.2 (Firefox)
  • 高级REST客户端9.14.64.305-stable (Chrome)

这些工具中的每一个的行为都是一样的:正常名称的HTTP头(如AB-CD )按预期工作; 名称为AB.CDAB%CD HTTP标头没有被nginx识别,并且没有显示在上述脚本的输出中。

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

尝试使用您的日志格式的escape参数:

从[nginx文档]: 1

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

文档是一切都很好,但真相的根本来源是源代码,甚至可能更容易find你的方式。 或者不 – YMMV。

http://lxr.nginx.org/source/src/http/modules/ngx_http_log_module.c中&#x7684;ngx_http_log_compile_format()函数是parsinglog_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指令中的variables名只能包含字母数字和“_”。

这不是故事的结尾,因为仍然存在一个包含'。'的标题的问题。 被映射到variables名称。

http://lxr.nginx.org/source/src/http/ngx_http_parse.c&#x5728;ngx_http_parse_header_line()中进行parsing。 还有一点要比我想要的更多。 看起来,如果代码命中“。” 在字段名称中,对字段名称的散列没有任何处理。 r->invalid_header = 1; 获取设置,但不return NGX_HTTP_PARSE_INVALID_HEADER; 如其他一些情况。 (见代码行922-982)。

我不在乎通过代码去探索什么r->invalid_header = 1; 确实,而且似乎没有必要。 log_format ... ${http_abcd} ...可能工作,如果这不起作用,那么我怀疑什么会。 我只是尝试一下,如果不行的话,不要担心。