我正在创建一个测试Go HTTP服务器,我正在发送Transfer-Encoding的响应头:chunked所以我可以在检索它时不断发送新数据。此服务器应每秒向此服务器写一个块。客户应该能够按需接收它们。
不幸的是,客户端(在这种情况下为curl)在持续时间结束时接收所有块,为5秒,而不是每秒接收一个块。此外,Go似乎为我发送了Content-Length。我想在最后发送Content-Length,我希望标题的值为0.
这是服务器代码:
package main
import (
"fmt"
"io"
"log"
"net/http"
"time"
)
func main() {
http.HandleFunc("/test", HandlePost);
log.Fatal(http.ListenAndServe(":8080", nil))
}
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")
}
答案 0 :(得分:22)
诀窍似乎是你需要在每个块写入后调用Flusher.Flush()
。另请注意" Transfer-Encoding"标题将由作者隐式处理,因此无需设置它。
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))
}
您可以使用telnet验证:
$ telnet localhost 8080
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
HTTP/1.1 200 OK
Date: Tue, 02 Jun 2015 18:16:38 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
9
Chunk #1
9
Chunk #2
...
您可能需要进行一些研究以验证http.ResponseWriters是否支持多个goroutine使用的并发访问。
另外,请参阅此问题以获取有关"X-Content-Type-Options" header。
的更多信息答案 1 :(得分:0)
看起来httputil提供了NewChunkedReader函数