HTTP 上下文截止日期被 json.NewDecoder().Decode() 忽略
问题:
当使用 context.WithTimeout 为 HTTP 请求建立时间限制时,ioutil.ReadAll 方法会在超过超时时中断请求并返回相应的错误。但是, json.NewDecoder(resp.Body).Decode 似乎忽略了截止日期,返回 nil 错误而不是 context.DeadlineExceeded。这是一个错误吗?
答案:
不,这不是一个错误。 net/http 包利用缓冲区来处理请求,因此有可能在程序读取响应正文之前将其部分或全部读入缓冲区。因此,过期的上下文不一定会阻止程序完成读取操作。
示例:
考虑一个故意延迟响应的修改后的 HTTP 测试服务器。当使用 readDoesntFail 时,服务器发送部分响应(10 个字节),刷新它,并等待 6 秒,然后发送剩余部分。
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { s := []byte(`{"ip":"12.34.56.78"}`) w.Write(s[:10]) if f, ok := w.(http.Flusher); ok { f.Flush() } time.Sleep(time.Second * 6) w.Write(s[10:])})) defer ts.Close()
在这种情况下,json.Decoder.Decode() 尝试读取由于数据尚未缓冲,因此无法连接。一旦上下文过期,从连接中进一步读取会触发 context.DeadlineExceeded 错误。
结论:
json.Decoder.Decode() 将遵守上下文截止时间数据尚未缓冲。然而,如果数据被部分或全部缓冲,则上下文截止时间可能不会阻止程序完成读取操作。建议使用 ioutil.ReadAll 或类似方法,以获得与上下文截止日期更一致的行为。
以上是为什么 `json.NewDecoder().Decode()` 不遵守 HTTP 上下文截止日期?的详细内容。更多信息请关注PHP中文网其他相关文章!