我们有一个 API 后端服务器,它要求某些 HTTP 标头包含下划线。我知道这不是最佳做法,标头应该使用连字符,但我无法更改这一点。
我们使用 nginx 作为带有选项的代理服务器underscores_in_headers on
。这导致 nginx 不会删除这些标头。
现在我们要切换到 HAProxy,并且像配置更改之前的 nginx 一样,它会删除带有下划线的标头。有没有办法防止 HAProxy 删除带有下划线的标头?
答案1
您是否实际测试过 HAProxy 是否会删除带有下划线的标头?
从源代码来看,似乎不是这样。在这个答案中,我将尝试解释:
- 为什么 HTTP 中允许在标头中使用下划线
- 为什么 Nginx 默认丢弃它们
- 为什么我认为 HAProxy 不会这样做。
HTTP/1.1 与 Nginx
根据 HTTP/1.1 规范RFC 7230 3.2.6,标题字段中使用下划线 ( ) 并没有错_
;它只是不常见。
字段值组件
大多数 HTTP 标头字段值使用通用语法组件(标记、带引号的字符串和注释)定义,这些组件由空格或特定分隔符分隔。分隔符从标记中不允许使用的 US-ASCII 可视字符集中选择(
DQUOTE
和(),/:;<=>?@[\]{}
)。token = 1*tchar tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA ; any VCHAR, except delimiters
Nginx 陷阱和常见错误:丢失(消失)的 HTTP 标头解释了为什么它们仍然默认被悄悄删除:
如果您未明确设置
underscores_in_headers on;
,NGINX 将默默删除带下划线的 HTTP 标头(根据 HTTP 标准,这些标头完全有效)。这样做是为了防止在将标头映射到 CGI 变量时出现歧义,因为在此过程中,破折号和下划线都会映射到下划线。
HAProxy
很遗憾,HAProxy 没有这样的设置. 如果您underscore
通过 HAProxy搜索配置手册,它只在以下上下文中被提及环境变量,节点名称(例如 DNS 名称),代理名称和ACL 名称. HTTP 请求章节中未提及。
如果 HAProxy 确实删除了带有下划线的标头,那么您将无法从配置中执行任何操作,并且必须坚持使用 Nginx 或修改 HAProxy 的源代码。
然而,我试图找到 HAProxy 丢弃标头的位置,但无法从proto_http.c
的功能void capture_headers()
和中找到这样的东西void http_msg_analyzer()
。
此外,proto_http.c
按类型列出所有 ASCII 字符,并(),/:;<=>?@[\]{}
列出为,HTTP_FLG_SEP
而下划线则列为普通标记:
495 /* It is about twice as fast on recent architectures to lookup a byte in a
496 * table than to perform a boolean AND or OR between two tests. Refer to
497 * RFC2616/RFC5234/RFC7230 for those chars. A token is any ASCII char that is
498 * neither a separator nor a CTL char. An http ver_token is any ASCII which can
499 * be found in an HTTP version, which includes 'H', 'T', 'P', '/', '.' and any
500 * digit. Note: please do not overwrite values in assignment since gcc-2.95
501 * will not handle them correctly. It's worth noting that chars 128..255 are
502 * nothing, not even control chars.
503 */
504 const unsigned char http_char_classes[256] = {
505 [ 0] = HTTP_FLG_CTL,
545 ['('] = HTTP_FLG_SEP,
546 [')'] = HTTP_FLG_SEP,
547 ['*'] = HTTP_FLG_TOK,
548 ['+'] = HTTP_FLG_TOK,
549 [','] = HTTP_FLG_SEP,
550 ['-'] = HTTP_FLG_TOK,
551 ['.'] = HTTP_FLG_TOK | HTTP_FLG_VER,
570 ['A'] = HTTP_FLG_TOK,
571 ['B'] = HTTP_FLG_TOK,
572 ['C'] = HTTP_FLG_TOK,
600 ['_'] = HTTP_FLG_TOK,
这里,只是像一样_
正常的,和;它不应该引起任何特殊情况。HTTP_FLG_TOK
A
B
C