dsgw8802 2017-06-21 13:00
浏览 137
已采纳

Golang HTTP服务器等待数据发送到客户端

I am creating a streaming API similar to the Twitter firehose/streaming API.

As far as I can gather this is based on HTTP connections that are kept open and when the backend gets data it then writes to the chucked HTTP connection. It seems that any code I write closes the HTTP connection as soon as anything connects.

Is there a way to keep this open at all?

func startHTTP(pathPrefix string) {
    log.Println("Starting HTTPS Server")
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // Wait here until a write happens to w
        // Or we timeout, we can reset this timeout after each write
    })

    log.Print("HTTPS listening on :5556")
    log.Fatal(http.ListenAndServeTLS(":5556", pathPrefix+".crt", pathPrefix+".key", nil))
}
  • 写回答

1条回答 默认 最新

  • dpe77294 2017-06-21 18:20
    关注

    When you want to send HTTP response to client not immediately but after some event, it's called long polling.

    Here's simple example of long polling with request cancellation on client disconnect:

    package main
    
    import (
        "context"
        "fmt"
        "net/http"
        "time"
    )
    
    func longOperation(ctx context.Context, ch chan<- string) {
        // Simulate long operation.
        // Change it to more than 10 seconds to get server timeout.
        select {
        case <-time.After(time.Second * 3):
            ch <- "Successful result."
        case <-ctx.Done():
            close(ch)
        }
    }
    
    func handler(w http.ResponseWriter, _ *http.Request) {
        notifier, ok := w.(http.CloseNotifier)
        if !ok {
            panic("Expected http.ResponseWriter to be an http.CloseNotifier")
        }
    
        ctx, cancel := context.WithCancel(context.Background())
        ch := make(chan string)
        go longOperation(ctx, ch)
    
        select {
        case result := <-ch:
            fmt.Fprint(w, result)
            cancel()
            return
        case <-time.After(time.Second * 10):
            fmt.Fprint(w, "Server is busy.")
        case <-notifier.CloseNotify():
            fmt.Println("Client has disconnected.")
        }
        cancel()
        <-ch
    }
    
    func main() {
        http.HandleFunc("/", handler)
        http.ListenAndServe("localhost:8080", nil)
    }
    

    URLs:

    1. Golang : anonymous struct and empty struct.
    2. Send a chunked HTTP response from a Go server.
    3. Go Concurrency Patterns: Context.

    Gists:

    1. Golang long polling example.
    2. Golang long polling example with request cancellation.
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?