frankenphp请求头丢失主因是代理层过滤、命名不规范及php映射规则:nginx默认丢弃含下划线的header(如auth_token);php将短横线头转为下划线大写键(如auth-token→$_server['http_auth_token']);需配置underscores_in_headers on或改用短横线命名,并显式proxy_set_header透传。

FrankenPHP 请求头丢失部分自定义 header,核心原因通常落在 请求头命名规范、代理层过滤、PHP 环境变量映射规则 这三层上,而不是 FrankenPHP 本身有 Bug。
自定义 Header 名含下划线(如 auth_token)被静默丢弃
FrankenPHP 运行在 SAPI 模式下,但若它前面有 Nginx 或 Caddy 做反向代理(这是常见部署方式),那么问题大概率出在代理层:
- Nginx 默认启用
underscores_in_headers off,会直接忽略所有字段名含_的请求头(如X-User_Id、auth_token); - 这类头不会转发给后端,FrankenPHP 根本收不到,
$_SERVER里自然查无此键。
✅ 解决办法:
- 在 Nginx 的
http{}或server{}块中显式开启:underscores_in_headers on;
- 更推荐的做法是统一改用短横线命名(如
auth-token→ PHP 中对应HTTP_AUTH_TOKEN),符合 HTTP 头命名惯例,也避免跨服务器兼容问题。
PHP 的 $_SERVER 映射规则导致“找不到”
FrankenPHP 遵循标准 PHP 行为:所有 HTTP 请求头都会被转成 $_SERVER['HTTP_XXX'] 形式,且自动做两件事:
- 全部转大写;
- 把
-替换为_(但_不会被替换,也不被识别为合法头)。
例如:
| 前端发送的 Header | PHP 中应访问的 $_SERVER 键 |
|------------------|----------------------------|
| X-Request-ID | $_SERVER['HTTP_X_REQUEST_ID'] |
| Auth-Token | $_SERVER['HTTP_AUTH_TOKEN'] |
| auth_token | ❌ 不出现(Nginx 已丢弃)或 $_SERVER['HTTP_AUTH_TOKEN'](若 Nginx 开了 underscores_in_headers on 且头名未被重写) |
⚠️ 注意:如果前端发的是 Auth_token(大小写混用),PHP 仍会归一化为 HTTP_AUTH_TOKEN,但某些代理可能因大小写敏感而误判为非法头。
反向代理未显式透传自定义头
即使 Nginx 开启了 underscores_in_headers on,它默认也不会把客户端的自定义头转发给后端。FrankenPHP 是后端服务,必须靠 proxy_set_header 显式传递:
location / {
proxy_pass http://127.0.0.1:8080; # FrankenPHP 监听地址
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Auth-Token $http_auth_token; # ← 关键:手动透传
proxy_set_header X-Request-ID $http_x_request_id;
}
? $http_xxx 变量名规则:
- 原头
Auth-Token→ 变量$http_auth_token; - 原头
X-Forwarded-For→$http_x_forwarded_for; - 原头
api_key(带下划线)→ 若underscores_in_headers on,才可用$http_api_key。
CORS 预检阶段导致 Header “看似丢失”
如果前端是跨域请求且带了非简单头(如 Auth-Token),浏览器会先发 OPTIONS 预检。
- 若 FrankenPHP 后端没正确响应
Access-Control-Allow-Headers: Auth-Token,浏览器就拒绝发送主请求; - 此时你以为“Header 没传过去”,其实是预检失败,根本没走到主请求阶段。
✅ 应确保响应中包含:
header('Access-Control-Allow-Headers: Auth-Token, Content-Type');
header('Access-Control-Expose-Headers: X-RateLimit-Remaining');
总结排查顺序
- 检查前端发出的 Header 名是否含
_,优先改为-; - 查看 Nginx 是否开了
underscores_in_headers on(多层代理需每层都开); - 确认 Nginx 的
proxy_set_header是否显式透传了目标头; - 在 FrankenPHP 中
var_dump($_SERVER),搜索HTTP_开头的对应键; - 对跨域请求,用浏览器 Network 面板确认是否卡在 OPTIONS 阶段。
不复杂但容易忽略。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











