I have a Golang program with a context deadline set. I am sending an HTTP request, and expected to see a deadline exceeded error when Im reading the body.
It seems that when I read the response body with ioutil.ReadAll then that read method will get interrupted (?) and return the appropriate error (context.DeadlineExceeded).
However if I read the response body with json.NewDecoder(resp.Body).Decode then the error returned is nil (instead of context.DeadlineExceeded). My full code is below. Is this a bug in json.NewDecoder(resp.Body).Decode?
package main
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)
var url string = "http://ip.jsontest.com/"
func main() {
readDoesntFail()
readFails()
}
type IpResponse struct {
Ip string
}
func readDoesntFail() {
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
panic(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
ipResponse := new(IpResponse)
time.Sleep(time.Second * 6)
fmt.Println("before reading response body, context error is:", ctx.Err())
err = json.NewDecoder(resp.Body).Decode(ipResponse)
if err != nil {
panic(err)
}
fmt.Println("Expected panic but there was none")
}
func readFails() {
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
panic(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
time.Sleep(time.Second * 6)
fmt.Println("before reading response body, context error is:", ctx.Err())
_, err = ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("received expected error", err)
}
}