I'm using context.Context to cancel a http request
I find although I got the "context cancel", the underlying socket connection is still available, and I can get the response after a few seconds. Is it designed this way to read response once request is set out?
This is the code
func SendRequest(ctx context.Context, url string) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println(err)
}
req = req.WithContext(ctx)
res, err := client.Do(req)
select {
case <-ctx.Done():
fmt.Printf("%s Canceled
", url)
//client.Transport.(*http.Transport).CancelRequest(req)
//client.Transport.(*http.Transport).CloseIdleConnections()
}
if res != nil {
defer res.Body.Close()
}
if err != nil {
fmt.Printf("Failed: %v
", err)
} else {
io.Copy(ioutil.Discard, res.Body)
fmt.Printf("return status: %d
", url, res.StatusCode)
}
}
The URL I'm requesting will return after several seconds, so I can still read the response body, and the connection was closed after the process exits.
Here is a simple code to reproduce the issue
func client() {
ctx, cancel := context.WithCancel(context.Background())
client := http.DefaultClient
request, _ := http.NewRequest("GET", "http://127.0.0.1:9090", nil)
req := request.WithContext(ctx)
go func() {
client.Do(req)
}()
time.Sleep(time.Duration(1) * time.Second)
cancel()
<-time.After(time.Duration(10) * time.Second)
}
func sayhelloName(w http.ResponseWriter, r *http.Request) {
time.Sleep(time.Duration(10) * time.Second)
fmt.Fprintf(w, "Hello world!")
}
func server() {
http.HandleFunc("/", sayhelloName)
err := http.ListenAndServe(":9090", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}