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
DDDoriginal
2024-12-09 09:21:09163parcourir

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")
}

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))
}

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

...

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!

Déclaration:
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