How to close HTTP/2 client stream when server closes request stream?

Created a HTTP/2 client and server program using net/http Go library for streaming client and server request response. Taken the reference from code here #13444 (comment) .

Server code

func handle_stream_request(w http.ResponseWriter, r *http.Request) {

buf := make([]byte, 1024)
i := 0
for {
	i = i + 1
	if(i == 10){
		break
	}
	len, _ := r.Body.Read(buf)
	response_str := "Server ACK for: " + string(buf[:len])
        w.Write([]byte(response_str))
        if f, ok := w.(http.Flusher); ok {
	   f.Flush()
        }
}


}

Client Code

func send_stream_request(client *http.Client){
pr, pw := io.Pipe()
req, _ := http.NewRequest("PUT", "https://localhost:8000/", ioutil.NopCloser(pr))
var res *http.Response

go func() {
	for {
		time.Sleep(2 * time.Second)
		s := "Client ping@" + get_time()
		pw.Write([]byte(s))
		if res != nil {
			buf := make([]byte, 1024)
			len, _ := res.Body.Read(buf)
			log.Printf("Response is: %s", string(buf[:len]))
		}
	}
}()

go func() {
	response, _ := client.Do(req)
	res = response
	log.Printf("\n Got: %#v", res)
}()
select {}

}

What did you expect to see?

After 10 requests from client the client program should exit successfully.

What did you see instead?

The client program blocks at writing at pipe “pw.Write([]byte(s))” after server has finished the handle function because there is no reader to read the data on pipe.

I am not able to understand how can I stop such client program from hanging. What signal does server send to client that request stream has been closed and it shouldn’t try to write more stuff on pipe.

1 Like

Write implements the standard Write interface: it writes data to the pipe, blocking until one or more readers have consumed all the data or the read end is closed. If the read end is closed with an error, that err is returned as err; otherwise err is ErrClosedPipe.

You are not handling the error pr.Write returns and not breaking the loop in the sender. That might be the reason.

1 Like

Thanks for the response. But above is a simplified code to make it short and easy to read. In my actual code, I did handle the error condition. But the problem is it just doesn’t proceed from “pw.Write([]byte(s))” after Server finished the request. I verified that by adding a print statement and through debugger as well.

I suspect, that it has something to do with net/http library which probably is not closing the Reader part of the pipe correctly, which is blocking the Writer also.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.