Search code examples
httpgohttp-postduplex

How to do an HTTP duplex handler in Go?


I heard here that

once you write anything in the response, the request body will be closed which prevents you from reading anything from it

If that is true, how can I write a proper duplex handler that is able to read from the request body, make some kind of transformation, and then write to the response body, in a streaming fashion just like people do in node.js ?


Solution

  • I ended up managing to do this with http.Hijacker.

    After the request is made and the request headers are parsed, I can read from *http.Request.Body, then hijack the connection and write to it, at the same time, like this:

    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()
    

    And then conn is a net.Conn which is the underlying TCP connection to the client, bufrw is a *bufio.ReadWriter, and to write the response without closing the body all I have to do is

    _, 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")
    

    And then I'm not sure about this but maybe someone can complete the answer, it's a good idea to flush the buffers down the connection once in a while with

    err := bufrw.Flush()