如何防止 HAProxy 丟棄帶有下劃線的 HTTP 標頭
我們有一個 API 後端伺服器,它需要某些包含下劃線的 HTTP 標頭。我知道這不是最佳做法,標題應該使用連字元,但我無法更改。
我們使用 nginx 作為代理伺服器,選項為
underscores_in_headers on
. 這會導致 nginx 不刪除這些標頭。現在我們要切換到 HAProxy 並在配置更改之前作為 nginx 刪除帶有下劃線的標頭。有沒有辦法防止 HAProxy 刪除帶有下劃線的標題?
您是否實際測試過 HAProxy 會丟棄帶有下劃線的標頭?
從原始碼來看,它似乎沒有。在這個答案中,我將嘗試解釋:
- 為什麼 HTTP 中允許標頭中的下劃線
- 為什麼 Nginx 預設會丟棄它們
- 為什麼我相信 HAProxy 不會這樣做。
HTTP/1.1 和 Nginx
根據RFC 7230 3.2.6
_
中的 HTTP/1.1 規範,標頭欄位中的下劃線 ( ) 沒有任何問題;這並不常見。欄位值組件
大多數 HTTP 標頭欄位值是使用由空格或特定定界字元分隔的通用語法組件(令牌、引用字元串和註釋)定義的。分隔符是從一組不允許在標記 (
DQUOTE
和(),/:;<=>?@[\]{}
) 中使用的 US-ASCII 視覺字元中選擇的。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
’s 函式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
; 它不應該引起任何特別的事情。