Go で単純な Web アプリを作成していて、応答をクライアントにストリーミングする必要があります (つまり、要求が完全に処理されると、バッファリングされず、ブロックで送信されます):
func handle(res http.ResponseWriter, req *http.Request) {
fmt.Fprintf(res, "sending first line of data")
sleep(10) //not real code
fmt.Fprintf(res, "sending second line of data")
}
クライアントの観点からは、2 つの回線が同時に送信されます。どんな提案でも大歓迎です:)
@dystroyの回答後に編集
個人的に書き込みを行うたびにフラッシュすることは可能ですが、私のユースケースでは十分ではありません:
cmd := exec.Command("a long command that outputs lots of lines")
cmd.Stdout = res //where res is a http.ResponseWritter
cmd.Stderr = res
err := cmd.Run()
私の出力cmd
もフラッシュしたい。とにかく ResponseWritter を「自動フラッシュ」するには?
解決
golang のメーリング リストでヘルプを見つけました。これを実現するには 2 つの方法があります。HTTP の基礎となる TCP 接続を引き継ぐことを許可するハイジャッカーを使用するか、書き込みとフラッシュを行う go ルーチンでコマンドの stdout と stderr をパイプします。
pipeReader, pipeWriter := io.Pipe()
cmd.Stdout = pipeWriter
cmd.Stderr = pipeWriter
go writeCmdOutput(res, pipeReader)
err := cmd.Run()
pipeWriter.Close()
//---------------------
func writeCmdOutput(res http.ResponseWriter, pipeReader *io.PipeReader) {
buffer := make([]byte, BUF_LEN)
for {
n, err := pipeReader.Read(buffer)
if err != nil {
pipeReader.Close()
break
}
data := buffer[0:n]
res.Write(data)
if f, ok := res.(http.Flusher); ok {
f.Flush()
}
//reset buffer
for i := 0; i < n; i++ {
buffer[i] = 0
}
}
}