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

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.
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 power BI 从Mysql服务器导入数据,但连接进去后显示表无数据
  • ¥15 (关键词-阻抗匹配,HFSS,RFID标签)
  • ¥50 sft下载大文阻塞卡死
  • ¥15 机器人轨迹规划相关问题
  • ¥15 word样式右侧翻页键消失
  • ¥15 springboot+vue 集成keycloak sso到阿里云
  • ¥15 win7系统进入桌面过一秒后突然黑屏
  • ¥30 backtrader对于期货交易的现金和资产计算的问题
  • ¥15 求C# .net4.8小报表工具
  • ¥15 安装虚拟机时出现问题