Rumah > pembangunan bahagian belakang > Golang > Mengapa Pelayan HTTP Go Saya Tidak Menghantar Respons Terpotong secara Progresif?

Mengapa Pelayan HTTP Go Saya Tidak Menghantar Respons Terpotong secara Progresif?

DDD
Lepaskan: 2024-12-09 09:21:09
asal
159 orang telah melayarinya

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

Tindak Balas HTTP Chunks daripada Pelayan Go

Dalam senario ini, kami berhasrat untuk mencipta pelayan HTTP Go yang menghantar respons HTTP chunk dengan Pemindahan-Pengekodan ditetapkan kepada "dipotong." Pelayan berhasrat untuk menulis potongan pada selang satu saat, membolehkan pelanggan menerimanya atas permintaan. Walau bagaimanapun, pelaksanaan semasa menghadapi cabaran:

  1. Pelanggan menerima semua bahagian sekaligus dan bukannya secara progresif seperti yang dimaksudkan.
  2. Pengepala Panjang Kandungan ditetapkan secara automatik oleh Go, yang kami mahu menjadi 0 dan ditambah pada penghujungnya.

Pelayan Kod

Kod pelayan yang disediakan adalah seperti berikut:

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")
}
Salin selepas log masuk

Penyelesaian

Untuk menyelesaikan isu:

  1. Antara muka "Flusher" yang dilaksanakan oleh http.ResponseWriter membolehkan kami mencetuskan penghantaran bongkah dengan memanggil Fungsi Flush(). Dengan menambahkan ini selepas setiap ketulan ditulis, pelanggan boleh menerima ketulan apabila ia sudah sedia.
  2. Pengepala Pemindahan-Pengekodan diuruskan secara automatik oleh penulis HTTP, jadi menetapkannya secara eksplisit adalah tidak diperlukan.

Disemak Kod

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))
}
Salin selepas log masuk

Pengesahan

Gunakan telnet untuk menyambung ke pelayan:

$ 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

...
Salin selepas log masuk

Setiap bahagian akan diterima secara progresif sebagai pelayan menghantarnya.

Atas ialah kandungan terperinci Mengapa Pelayan HTTP Go Saya Tidak Menghantar Respons Terpotong secara Progresif?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan