Comportement inattendu de json.NewDecoder().Decode() dans le délai contextuel
Dans les programmes Go avec un délai contextuel défini, la réponse le corps lu par ioutil.ReadAll() devrait renvoyer une erreur (context.DeadlineExceeded). Cependant, ce comportement n'est pas observé lors de la lecture du corps de la réponse avec json.NewDecoder(resp.Body).Decode(), qui renvoie nil.
Approfondissons le problème :
Selon les réponses, le package net/http peut utiliser des tampons pour traiter les requêtes. Cela implique que le corps de la réponse entrante peut être partiellement ou entièrement lu et mis en mémoire tampon avant que vous ne le fassiez. Par conséquent, un contexte expirant peut ne pas vous empêcher de terminer la lecture du corps.
Pour illustrer cela plus clairement, nous avons ajusté un exemple pour lancer un serveur HTTP de test qui retarde délibérément partiellement la réponse :
<code class="go">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() url = ts.URL readDoesntFail() readFails()</code>
Ce serveur de test génère un objet JSON ressemblant à la réponse de ip.jsontest.com. Contrairement à cela, il ne fournit initialement que 10 octets de corps, puis les vide et se met en veille intentionnellement pendant 6 secondes avant de transmettre le reste, donnant au client le temps d'expirer.
Lorsque nous exécutons readDoesntFail() avec ce serveur , nous obtenons :
before reading response body, context error is: context deadline exceeded panic: Get "http://127.0.0.1:38230": context deadline exceeded goroutine 1 [running]: main.readDoesntFail() /tmp/sandbox721114198/prog.go:46 +0x2b4 main.main() /tmp/sandbox721114198/prog.go:28 +0x93
Maintenant, avec notre exemple mis à jour, json.Decoder.Decode() fait un effort pour lire à partir de la connexion car les informations ne sont pas encore mises en mémoire tampon, permettant à l'expiration du contexte de provoquer un erreur due à un contexte expiré.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!