HTTP 协议中带下划线的 header 说明


HTTP Header 名字的规范

RFC9110 中说,Field Name 应该 仅包含字母数字,连字符(-), 第一个字符是字母,不区分大小写。

The requested field name. It MUST conform to the field-name syntax defined in Section 5.1, and it SHOULD be restricted to just letters, digits, and hyphen (’-’) characters, with the first character being a letter.

自定义专用的标头之前可以与 X- 前缀一起使用,但是这种用法被 IETF 在 2012 年 6 月发布的 RFC 6648 明确弃用,原因是其会在非标准字段成为标准时造成不便;

一个标准的 HTTP Header 诞生要经历漫长的过程,而且我们的 Header 中如果有业务前缀的话,基本不会和标准 HTTP Header 冲突,所以很多文章说使用 X- 前缀也没有什么问题。

Nginx 的 ignore_invalid_headers 配置文档中说,Http Header 名称由字母数字,连字符组成,underscores_in_headers 开启时可以包含下划线。

当在 Nginx 中设置了 ignore_invalid_headers on; 时, Nginx 会自动丢弃名称无效的 Header 。

如何让 Nginx 允许 Header 名中带下划线

Nginx 的选项 underscores_in_headers 可以允许我们在 HTTP Header 的名字中带上下划线。

Enables or disables the use of underscores in client request header fields. When the use of underscores is disabled, request header fields whose names contain underscores are marked as invalid and become subject to the ignore_invalid_headers directive.

实验

使用 nc 启动一个 http server

  • /tmp/index.http
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 77
Server: netcat!

<!doctype html>
<html><body><h1>A webpage served by netcat</h1></body></html>
  • 使用 nc 启动 web server
while true;do cat /tmp/index.http| nc -l -p 8090 ;done

注意: 不能使用 flask 作为后端

Python 的 wsgi 解析器或 Flask 中会自动丢掉名字中带下划线的 header, 使用 flask 作为后端,就算 Nginx 传了下划线 Header 我们也看不到。

使用 nc 作为后端 Web Server, 它会原样输出 nginx 传输给它的内容。

我们使用 curl 命令给 Nginx Server 发送带下划线的 Header

curl -H 'Some_Header: V1' -s flask.bwangel.me

默认不会传输带下划线的 Header

server {
    listen 80;

    server_name flask.bwangel.me;

    location / {
        proxy_set_header Nginx-Host "flask";
        proxy_pass http://127.0.0.1:8090;
    }
}

image

图中上半部分是 nc web server 输出的内容,可以看到 Some_Header 没有被 Nginx 传输给后端.

关闭 ignore_invalid_headers

server {
    listen 80;

    server_name flask.bwangel.me;
    ignore_invalid_headers off;

    location / {
        proxy_set_header Nginx-Host "flask";
        proxy_pass http://127.0.0.1:8090;
    }
}

关闭了 ignore_invalid_headers 之后,无效的 header 也会被 Nginx 传输给后端了

image

上图中,可以看到 Some_Header 被 Nginx 传输给了后端

开启 underscores_in_headers

server {
    listen 80;

    server_name flask.bwangel.me;
    underscores_in_headers on;
    ignore_invalid_headers on;

    location / {
        proxy_set_header Nginx-Host "flask";
        proxy_pass http://127.0.0.1:8090;
    }
}

image

可以看到,开启了 underscores_in_headers 之后,带下划线的 header 就是有效的 header 了,就算开着 ignore_invalid_headers, nginx 也会将 Some_Header 传输给后端。

参考链接

2023年05月09日 / 22:40