Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Document how to have read timeout be larger than idle timeout

未关闭
#425 3 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
20/100
Issue 类型
功能
描述清晰度
需要澄清
活跃度
停滞
技术栈
go
领域
api, networking

调研方向

首先阅读 Reader 入口点和 Conn.msgReader,然后查看关联的 issue 87 以及示例中展示的 context 行为。确定当前 API 是否支持为获取 Reader 和完成读取分别设置时间限制,并记录受支持的方法或所需的 API 设计变更。

由索引模型根据 Issue 内容生成。

描述

docs

Hi! Thanks for this excellent library.

I have a use case where I want the server to wait up to 10 seconds for the client to start sending data. If the server doesn't get a new Reader within that time, it closes the connection and bails.

However, if the client does start sending data, then they have a much longer time limit to finish sending. Say 2 minutes. As far as I can tell, there's not a good way to accomplish this with the current API design.

I saw this issue: https://github.com/nhooyr/websocket/issues/87

Which works IFF the idle timeout is larger than the read timeout.

This is because the Conn.msgReader holds on to the context passed in during Reader() Example:

ctx, cancel := context.WithTimeout(rootCtx, 10 *second)
defer cancel()

_, reader, err := ws.Reader(ctx)
if err != nil {
	// Err handling....
	log.Error(err)
	return
}

// If reading data takes longer than 10 seconds, the timeout above will fire, and the context will be cancelled
// Killing the connnection
data, err := io.ReadAll(reader)
if err != nil {
	// Err handling....
	log.Error(err)
	return
}

I can potentially work around this. Instead of using context.WithTimeout, I could just use context.WithCancel. Then have a time.AfterFunc(), which uses atomics to check if we got the reader already. In which case, don't cancel. Example:

ctx, cancel := context.WithCancel(rootCtx)
defer cancel()

gotReader := atomic.Bool{}

time.AfterFunc(10*time.Second, func() {
	if !gotReader.Load() {
		cancel()
	}
})

_, reader, err := ws.Reader(ctx)
if err != nil {
	// Err handling....
	log.Error(err)
	return
}
gotReader.Store(true)

time.AfterFunc(2*time.Minute, func() {
	cancel()
})

data, err := io.ReadAll(reader)
if err != nil {
	// Err handling....
	log.Error(err)
	return
}

I'm not sure what the best way to modify the API would be. You're unfortunately stuck with the io.Reader interface, without the ability to add a context. Thoughts?

主要语言
Go
星标
5.5k
派生
379
PR 合并指标
30 天内没有已合并 PR

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

coder/websocket 的其他 Issue

查看 coder/websocket 的全部 Issue

相似的 Issue

更多 Go Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。