Karp 的技术博客

背景

在一次前后端联调中,前端在请求中新增了一个 Header:


x_log_id: 123456

结果接口直接报错。

经过排查发现:

  • 浏览器 Network 中 Header 是存在的
  • 后端却 完全接收不到
  • Nginx 已配置 CORS:

add_header Access-Control-Allow-Headers $http_access_control_request_headers always;

但问题依然存在。

最终,前端将 Header 改为:


x-log-id: 123456

问题立刻解决。

这到底是为什么?


一、问题的根源不是 CORS

一开始很容易误判为 CORS 问题,毕竟是「自定义 Header + 跨域」。

但实际上:

  • OPTIONS 预检请求是通过的
  • 浏览器也确实把 Header 发出去了
  • 问题发生在 Nginx 到后端这一层

二、HTTP Header 命名规范

1️⃣ 标准推荐的写法

HTTP Header 的标准(RFC 7230 / RFC 9110)中:

  • Header 名称由 token 构成
  • 历史和实际约定中:

    • 推荐使用 -(连字符)
    • 不推荐使用 _(下划线)

常见合法写法:


X-Request-Id
X-Trace-Id
Content-Type

而不是:


x_request_id
x_log_id

三、Nginx 的默认行为(关键点)

1️⃣ Nginx 默认会忽略带 _ 的请求头

Nginx 有一个非常关键但容易被忽略的配置项:


underscores_in_headers off;  # 默认值

默认行为是:

  • 请求 Header 中如果包含 _
  • Nginx 会直接丢弃该 Header
  • 该 Header:

    • $http_xxx 中取不到
    • 不会被转发到后端

这也是为什么:

浏览器能看到
后端却完全接收不到

四、为什么 CORS 配置解决不了?

你可能已经加了:


add_header Access-Control-Allow-Headers $http_access_control_request_headers always;

这个配置的作用是:

  • 告诉浏览器:
    “我允许你发送这些 Header”

但它 无法影响 Nginx 自身是否接收 Header

换句话说:

浏览器:我发了
Nginx:我不要

五、为什么改成 x-log-id 就好了?


x-log-id

具备以下特点:

  • 使用 -,符合规范
  • Nginx 默认支持
  • 不需要任何额外配置
  • Header 可以完整传递给后端

因此问题立刻消失。


六、可选解决方案(不推荐)

如果你 必须 使用下划线(强烈不推荐),可以在 Nginx 中显式开启:


underscores_in_headers on;

⚠️ 注意:

  • 可能带来安全风险
  • 与部分代理、网关行为不一致
  • 不符合主流 HTTP 规范

七、最佳实践建议

Header 命名规范

  • 使用 -
  • 小写或首字母大写均可(HTTP Header 不区分大小写)

推荐示例:


X-Request-Id
X-Trace-Id
X-Log-Id

❌ 避免:


x_log_id
trace_id
request_id

八、总结

问题原因
Header 在浏览器存在浏览器正常发送
后端收不到Nginx 丢弃 _ Header
CORS 无法解决问题不在浏览器
改成 - 立刻好符合规范 + Nginx 默认支持

结论一句话:

这是一个典型的「HTTP 规范 + Nginx 默认行为」导致的坑,而不是前端或 CORS 的锅。

nginx

版权属于:karp
作品采用:本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
更新于: 2026年01月19日 12:25
0

目录

来自 《 [踩坑] 一次诡异的 Header 丢失问题:为什么 x_log_id 会导致接口报错?》