最直接方式是用responseinterface的withheader()方法并显式return新响应对象,因其不可变性;漏return则静默失效,且withheader()会覆盖同名头,追加需用withaddedheader()。

Hyperf 控制器里设置响应头,最直接的方式是通过 ResponseInterface 实例的 withHeader() 方法 —— 但要注意它返回的是新响应对象,不是原地修改,漏掉 return 就会静默失效。
用 withHeader() 设置单个或多个响应头
Hyperf 的 ResponseInterface(如 $response 参数)遵循 PSR-7 规范,所有 header 操作都是不可变的。必须显式 return 新响应:
常见写法示例:
public function index(ResponseInterface $response): ResponseInterface
{
return $response
->withHeader('Content-Type', 'application/json; charset=utf-8')
->withHeader('X-Frame-Options', 'DENY')
->withHeader('X-Content-Type-Options', 'nosniff');
}
注意:withHeader() 会覆盖同名 header;若需追加(比如多个 Set-Cookie),用 withAddedHeader()。
- 不要写成
$response->withHeader(...); return $response;—— 这样 header 没生效 -
Content-Type不强制要设,json()/xml()等快捷方法已内置,但自定义类型或覆盖时必须显式调用withHeader() - 敏感 header 如
Set-Cookie在反向代理(Nginx)后可能被拦截,需确认 Nginx 配置未用proxy_hide_header Set-Cookie
EventStream 场景必须关闭缓冲和缓存
做 SSE(Server-Sent Events)流式推送时,浏览器要求响应头严格匹配,且服务端不能缓存或缓冲输出:
关键 header 缺一不可:
Content-Type: text/event-streamCache-Control: no-cacheConnection: keep-alive-
X-Accel-Buffering: no(告诉 Nginx 禁用缓冲,否则流卡住)
示例:
public function stream(ResponseInterface $response): ResponseInterface
{
return $response
->withHeader('Content-Type', 'text/event-stream')
->withHeader('Cache-Control', 'no-cache')
->withHeader('Connection', 'keep-alive')
->withHeader('X-Accel-Buffering', 'no');
}
漏掉 X-Accel-Buffering: no 是生产环境最常导致“连接建立但无数据”问题的原因 —— Nginx 默认开启缓冲,会攒够 4KB 才发,SSE 流就卡死了。
批量设置 header:用 withHeaders() 或中间件统一处理
如果多个接口都要加同一组安全头(如 CSP、HSTS),重复写 withHeader() 易出错。推荐两种方式:
- 用
withHeaders(array $headers)一次注入多个:$response->withHeaders(['X-Frame-Options' => 'DENY', 'Referrer-Policy' => 'no-referrer']) - 更推荐抽成全局中间件,在
config/autoload/middlewares.php中注册,对所有请求统一加 header,避免遗漏 - 注意中间件中修改响应头,也要 return 新响应对象,不能只调用
withHeader()后不返回
中间件里典型写法:
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$response = $handler->handle($request);
return $response->withHeader('X-Permitted-Cross-Domain-Policies', 'none');
}
Hyperf 的响应头操作本身很简单,真正容易出问题的是上下文:header 是否被后续中间件覆盖、是否被 Nginx 屏蔽、是否在流式场景下被缓冲。重点盯住 X-Accel-Buffering 和 proxy_hide_header 这两个点,比反复检查 PHP 代码更容易定位问题。











