Unexpected net/http context cancellation

3,056 views
Skip to first unread message

jesse....@gmail.com

unread,
Jan 15, 2018, 12:04:19 PM1/15/18
to golang-nuts
According to https://golang.org/pkg/net/http/#Request.Context:

For incoming server requests, the context is canceled when the client's connection closes, the request is canceled (with HTTP/2), or when the ServeHTTP method returns.

My expectation, then, is for the following code to block:

package main

import (
       
"fmt"
       
"io/ioutil"
       
"net/http"
)

func main
() {
        s
:= &http.Server{
               
Addr: ":8080",
               
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                        ioutil
.ReadAll(r.Body)

                       
<-r.Context().Done()

                        w
.Write([]byte(fmt.Sprintf(
                               
"request context done: %+v\n",
                                r
.Context().Err(),
                       
)))
               
}),
       
}
        s
.ListenAndServe()
}



Instead, it always returns immediately, reporting that the context was canceled:

> printf "POST / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 4\r\n\r\nbody" | nc localhost 8080
HTTP
/1.1 200 OK
Date: Mon, 15 Jan 2018 16:01:46 GMT
Content-Length: 39
Content-Type: text/plain; charset=utf-8


request context
done: context canceled


Curiously, if I don't ioutil.ReadAll(r.Body), the request blocks as expected.

Am I missing something? My hope was to be able to use the default context to detect client disconnection.

Axel Wagner

unread,
Jan 15, 2018, 12:49:05 PM1/15/18
to jesse....@gmail.com, golang-nuts
I assume netcat closes the connection once it gets an EOF from stdin. Thus the server notices the client disconnecting and cancels the context, as advertised.
Try running nc without piping the input in and typing it out on the console.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

jesse....@gmail.com

unread,
Jan 15, 2018, 1:44:46 PM1/15/18
to golang-nuts
Thank you -- that makes sense. I was initially thrown off by the fact that the connection remains open for netcat to get the full HTTP response.

For posterity, another way to get the desired behaviour is to invoke netcat as follows, noting that it won't exit by itself anymore:

> cat ~/tmp/payload - | nc localhost 8080

To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages