Search code examples
httpgogo-http

Sending HTTP Put body from ReadCloser never ends


Target

I want to send to data to my server from a read closer. (In the example a NopCloser, later it will be the Stdout of an exec.Command)

Problem

The Request never ends. Even if I manually close the cmdOut the program nevers ends. Concrete: It never reaches the "Request Done" line and there by never calls wg.Done()

Gotchas

All the data is sent correctly to the server (even with the exec.Command Stdout). But the http.DefaultClient.Do seems to be still listening on the ReadCloser after it is empty (and closed in the main routine)

Code

cmdOut := ioutil.NopCloser(bytes.NewBuffer([]byte("Hallo DU")))

var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()

    // localhost:1234 is a netcat server: "nc -l -p 1234"
    req, _ := http.NewRequest("PUT", "http://localhost:1234", cmdOut)

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Println(err)
        return
    }

    // Never reaches this line
    log.Println("Request Done")
}()

cmdOut.Close()

log.Println("Wait for go routine")
wg.Wait()
log.Println("DONE")

Solution

  • The problem isn't the sending of your request--it's the receiving of the response.

    You're sending your request to netcat, which simply discards the request, and does nothing else. This leaves the HTTP client library waiting for an HTTP response, which never comes.

    The solution is to talk to an actual HTTP server.