Iris中Context.Write不能直接用于流式响应,因默认启用响应缓冲,需显式禁用缓冲、设置正确Header(如text/event-stream)、调用Flush(),或使用Hijack()/ResponseController实现可靠流式推送。

iris.Context.Write 不能直接用于流式响应
直接在 handler 里反复调用 c.Write 或 c.WriteString 不会触发分块传输(chunked transfer encoding),HTTP 响应仍会被 Iris 缓存并一次性发出,除非你显式禁用缓冲并手动控制 Header 和底层连接。
根本原因是 Iris 默认启用响应缓冲(context.ResponseWriter 是包装过的),Write 只写入缓冲区,直到 handler 返回或显式 c.ResponseWriter().Flush() 才可能下发——但即使 flush,也不保证客户端收到的是合法 chunked 流,尤其当未设置正确 Header 时。
- 必须先调用
c.ResponseWriter().Header().Set("Content-Type", "text/event-stream")或"application/json"(取决于前端解析方式) - 必须设置
Transfer-Encoding: chunked—— 但 Iris 不允许手动设这个 Header;正确做法是:不设Content-Length,且确保响应体未被提前结束 - 关键一步:调用
c.ResponseWriter().Flush()每次写完一块后,否则数据卡在缓冲区
用 iris.Context.ResponseWriter().Hijack 实现可靠流式推送
当需要完全控制连接(比如 SSE 或自定义 chunked JSON 流),Hijack() 是最直接的方式。它绕过 Iris 的响应生命周期,拿到原始 net.Conn 和 bufio.ReadWriter,适合长连接、持续写入场景。
注意:Hijack 后 Iris 不再管理该连接,你需自行处理错误、超时、连接关闭检测,且不能再调用任何 c.*() 方法(会 panic)。
- 必须在
Hijack前设置好状态码和必要 Header,例如:c.StatusCode(200)、c.Header("Content-Type", "text/event-stream") - 调用
conn, bufrw, err := c.ResponseWriter().Hijack(),检查err,失败则退回到普通响应 - 每次写入后调用
bufrw.Flush(),否则数据不会真正发出去 - 建议加
defer conn.Close(),并在写循环中监听conn.RemoteAddr()是否断开(可读io.EOF或net.ErrClosed)
示例片段:
func streamHandler(c iris.Context) {
c.StatusCode(200)
c.Header("Content-Type", "text/event-stream")
c.Header("Cache-Control", "no-cache")
c.Header("Connection", "keep-alive")
<pre class="brush:php;toolbar:false;">conn, bufrw, err := c.ResponseWriter().Hijack()
if err != nil {
c.StopWithError(iris.StatusInternalServerError, err)
return
}
defer conn.Close()
for i := 0; i <p>}</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2762" title="Iris框架 12.2.5"><img
src="https://img.php.cn/upload/manual/001/589/237/6aa35e21a9024187.png" alt="Iris框架 12.2.5" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2762" title="Iris框架 12.2.5" class="overflowclass">Iris框架 12.2.5</a>
<p class="overflowclass">Iris框架 12.2.5 版本源码包下载,适合需要 MVC Singleton 控制器、依赖注入字段控制和 debug 错误日志改进的开发者。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2762" title="Iris框架 12.2.5" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
用 PassThrough + http.ResponseController(Go 1.22+)更安全
如果你用的是 Go 1.22 或更高版本,且 Iris 已升级支持 http.ResponseController(v12.2.5+ 确认兼容),推荐用标准库的流式机制,比 Hijack 更可控、不易出错。
核心是获取 http.ResponseController 并调用 SetUncompressed(true),再配合 io.Copy 或手动写入,让 net/http 自动启用 chunked 编码。
- 必须确保 Iris 未提前写入响应头或 body(即 handler 内尚未调用任何
c.Write*) - 从
c.ResponseWriter()获取http.ResponseWriter接口,再用http.NewResponseController包装 -
SetUncompressed(true)是关键,它告诉 http.Server 不要 gzip,同时启用 chunked - 后续所有写入都走
bufrw并Flush(),无需Hijack
常见错误:前端收不到 chunk、连接立即关闭
现象包括:浏览器 Network 面板只看到 pending,或收到完整响应后才渲染;fetch 收到 TypeError: Failed to fetch;SSE 连接秒断。
90% 是因为没做这三件事之一:
- 忘了设
Content-Type为text/event-stream(SSE)或留空(chunked JSON) - 响应头里意外带了
Content-Length(Iris 某些中间件或日志插件会自动加,需排查) - handler 执行完就退出,而流式逻辑还在 goroutine 里跑——必须把流式写入和 handler 生命周期对齐,要么阻塞 handler,要么用 channel 控制生命周期
最容易被忽略的一点:Nginx 或 Cloudflare 默认会缓冲响应,导致 chunked 流被攒成整包才转发。必须在反向代理配置里显式开启流式支持,例如 Nginx 加:proxy_buffering off;、chunked_transfer_encoding on;。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










