Maison > développement back-end > Golang > Pourquoi mon serveur HTTP Go n'envoie-t-il pas progressivement les réponses fragmentées ?

Pourquoi mon serveur HTTP Go n'envoie-t-il pas progressivement les réponses fragmentées ?

DDD
Libérer: 2024-12-09 09:21:09
original
158 Les gens l'ont consulté

Why Doesn't My Go HTTP Server Send Chunked Responses Progressively?

Réponse HTTP Chunks d'un serveur Go

Dans ce scénario, nous visons à créer un serveur HTTP Go qui envoie une réponse HTTP fragmentée avec Transfer-Encoding défini sur « chunked ». Le serveur a l'intention d'écrire des morceaux à intervalles d'une seconde, permettant au client de les recevoir à la demande. Cependant, la mise en œuvre actuelle est confrontée à des défis :

  1. Le client reçoit tous les morceaux en même temps au lieu de progressivement comme prévu.
  2. L'en-tête Content-Length est automatiquement défini par Go, que nous veut être 0 et ajouté à la fin.

Code du serveur

Le le code du serveur fourni est le suivant :

func HandlePost(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Connection", "Keep-Alive")
    w.Header().Set("Transfer-Encoding", "chunked")
    w.Header().Set("X-Content-Type-Options", "nosniff")

    ticker := time.NewTicker(time.Second)
    go func() {
        for t := range ticker.C {
            io.WriteString(w, "Chunk")
            fmt.Println("Tick at", t)
        }
    }()
    time.Sleep(time.Second * 5)
    ticker.Stop()
    fmt.Println("Finished: should return Content-Length: 0 here")
    w.Header().Set("Content-Length", "0")
}
Copier après la connexion

Solution

Pour résoudre les problèmes :

  1. L'interface "Flusher" implémentée par http.ResponseWriter nous permet de déclencher l'envoi de chunks en appelant la fonction Flush(). En ajoutant ceci après l'écriture de chaque morceau, le client peut recevoir les morceaux dès qu'ils sont prêts.
  2. L'en-tête Transfer-Encoding est automatiquement géré par l'en-tête HTTP, il n'est donc pas nécessaire de le définir explicitement.

Révisé Code

import (
  "fmt"
  "io"
  "log"
  "net/http"
  "time"
)

func main() {
  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    flusher, ok := w.(http.Flusher)
    if !ok {
      panic("expected http.ResponseWriter to be an http.Flusher")
    }
    w.Header().Set("X-Content-Type-Options", "nosniff")
    for i := 1; i <= 10; i++ {
      fmt.Fprintf(w, "Chunk #%d\n", i)
      flusher.Flush() // Trigger "chunked" encoding and send a chunk...
      time.Sleep(500 * time.Millisecond)
    }
  })

  log.Print("Listening on localhost:8080")
  log.Fatal(http.ListenAndServe(":8080", nil))
}
Copier après la connexion

Vérification

Utilisez telnet pour vous connecter au serveur :

$ telnet localhost 8080
...
HTTP/1.1 200 OK
Date: ...
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked

9
Chunk #1

9
Chunk #2

...
Copier après la connexion

Chaque morceau sera reçu au fur et à mesure le serveur les envoie.

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!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal