【问题标题】:How to do an HTTP duplex handler in Go?如何在 Go 中做一个 HTTP 双工处理程序?
【发布时间】:2013-11-04 15:31:50
【问题描述】:

我听说here那个

在响应中写入任何内容后,请求正文将是 关闭它会阻止您从中读取任何内容

如果这是真的,我如何编写一个适当的双工处理程序,它能够从请求正文中读取,进行某种转换,然后以流式方式写入响应正文,就像人们在节点中所做的那样.js ?

【问题讨论】:

    标签: http go http-post duplex


    【解决方案1】:

    我最终设法通过http.Hijacker 做到了这一点。

    发出请求并解析请求头后,我可以从*http.Request.Body读取,然后劫持连接并同时写入,如下所示:

    hj, ok := w.(http.Hijacker)
    if !ok {
        http.Error(w, "hijacking not supported", 500)
        return
    }
    
    conn, bufrw, err := hj.Hijack()
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
    defer conn.Close()
    

    然后connnet.Conn,这是到客户端的底层 TCP 连接,bufrw*bufio.ReadWriter,并且在不关闭正文的情况下编写响应我所要做的就是

    _, err = bufrw.WriteString("HTTP/1.1 200 OK\n\n")
    _, err = bufrw.WriteString("this")
    _, err = bufrw.WriteString("is")
    _, err = bufrw.WriteString("the")
    _, err = bufrw.WriteString("response")
    _, err = bufrw.WriteString("body")
    

    然后我不确定这一点,但也许有人可以完成答案,不时将缓冲区刷新到连接中是个好主意

    err := bufrw.Flush()
    

    【讨论】:

      【解决方案2】:

      来自您所指的net/http docs

      var ErrBodyReadAfterClose = errors.New("http: 关闭时读取无效 身体")

      读取请求或响应时返回 ErrBodyReadAfterClose 身体关闭后的身体。这通常发生在 在 HTTP 处理程序调用 WriteHeader 或 Write 后读取正文 响应者

      但是我尝试了您提到的博客文章中链接的代码,它在 go 1.1.2 下运行良好,除非我先写入超过 4k 的数据,在这种情况下 r.ParseForm() 返回 ErrBodyReadAfterClose

      所以我认为答案是否定的,除非响应很短(低于 4k),否则通常不能在 go 中执行全双工 HTTP。

      我想说的是,执行全双工 HTTP 请求不太可能带来很大的好处,因为大多数客户端在完成发送请求之前不会尝试从响应中读取,所以你会赢得最多的是大小客户端和服务器中的 TCP 缓冲区。如果超出这些缓冲区,可能会出现死锁,例如

      • 客户端正在发送请求
      • 服务器正在发送响应
      • 服务器缓冲区获得完整的发送响应
      • 服务器块
      • 服务器不再读取客户端请求
      • 客户端缓冲区已满
      • 客户端块
      • 死锁

      【讨论】:

      • 我不了解大多数客户端,但任何 node.js 客户端都可以做到,这就是我的出发点。如果这会成为问题,我将不得不更好地处理缓冲区
      猜你喜欢
      • 1970-01-01
      • 2023-01-04
      • 1970-01-01
      • 2018-12-21
      • 1970-01-01
      • 2019-08-27
      • 2012-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多