json.NewDecoder().Decode() によって HTTP コンテキストの期限が無視されました
質問:
context.WithTimeout を使用して HTTP リクエストの時間制限を設定する場合、タイムアウトを超えると ioutil.ReadAll メソッドはリクエストを中断し、適切なエラーを返します。ただし、json.NewDecoder(resp.Body).Decode は期限を無視しているようで、context.DeadlineExceeded ではなく nil エラーを返します。これはバグですか?
答え:
いいえ、これはバグではありません。 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 中国語 Web サイトの他の関連記事を参照してください。