routermiddleware必须前置且server名需严格匹配,否则header无法获取;nginx代理时需开启underscores_in_headers on以保留下划线header。

Hyperf 中拿不到请求 Header(比如 Authorization、X-Request-ID),八成不是代码写错了,而是中间件在 Router 解析前就截断了请求,或者压根没加载到——Header 还没被解析出来,就被丢弃或覆盖了。
RouterMiddleware 必须排在最前面
Hyperf 的路由信息(包括路径、方法、注解绑定的控制器)全靠 RouterMiddleware 解析并写入 $request->getAttribute('route')。如果它被其他中间件挡在后面,后续所有依赖路由信息或原始 Header 的逻辑都会失效。
- 典型现象:
GET /api/user返回 404,且日志里$request->getAttribute('route')是null - AuthMiddleware、PermissionMiddleware 等若放在
RouterMiddleware前,会因无法获取路由参数而直接 throw 异常或返回 401 -
RouterMiddleware类名是\Hyperf\HttpServer\Middleware\RouterMiddleware::class,必须显式出现在middlewares.php的最高优先级位置(如设为=> 100) - 别指望“数组顺序”,必须用数值优先级:数值越大越早执行(请求阶段)
server 名不匹配导致中间件组静默失效
Hyperf 的 config/autoload/middlewares.php 是按 server 名分组生效的,不是全局配置。键名不匹配,中间件根本不会加载,框架也不报错——这是最隐蔽的坑。
Hyperf 3.2.3于2026年7月30日发布,是3.2分支的官方维护版本,新增支持函数,并修复模型注释、缓存组件文档、数据库模型构建器注释和关联预加载字段等问题。
- 打开
config/autoload/server.php,检查servers数组中每个name值(比如'name' => 'api') - 再核对
middlewares.php的键名是否完全一致:大小写、空格、下划线都不能差一点 - 默认
'http'键只在 server 名确实是'http'时才生效;自定义名如'admin',就必须写'admin' => [...] - 用
var_dump(config('server.servers'))和var_dump(config('middlewares'))对比验证
HEAD 请求会清空自定义响应头
Hyperf 对 HEAD 请求的处理是复用 GET 逻辑,但内部会调用 Response::withStatus() 触发头重置,导致你在控制器或中间件里设置的 X-* 类响应头全部丢失。
- 现象:GET 正常返回
X-Request-ID,HEAD 却没有 - 原因:框架未透传原始响应头,而是新建一个空头集合
- 解决方式:在控制器中对
HEAD显式调用$response->withHeader('X-Request-ID', $id) - 更稳妥的做法:为
HEAD单独定义路由或方法(如#[HeadMapping('/user')]),避免 fallback 到 GET 处理器
NGINX 代理会默认过滤带下划线的 Header
如果你用 NGINX 做反向代理,且 Header key 含下划线(如 auth_token、x_api_key),NGINX 默认会丢弃它们——这不是 Hyperf 的问题,但表现就是“收不到”。
- 错误现象:本地直连 Hyperf 能收到
auth_token,走 NGINX 就为空 - 检查 NGINX 配置是否包含
underscores_in_headers on;(需加在http或server块) - 不建议改 Header 名来迁就 NGINX,应开启该选项并确保它生效(可加
error_log /var/log/nginx/error.log notice;查看警告) - 测试命令:
curl -H "auth_token: abc" http://your-domain.com/api/test,对比直连与代理结果
Header 拿不到,往往不是某一行代码错了,而是整个请求生命周期里某个环节“没被看见”。重点盯住 RouterMiddleware 是否就位、server 名是否对得上、NGINX 是否悄悄吃了头——这三处漏掉任何一个,都可能让 Header 在抵达业务层前就消失了。










