-
-
Save decoomanj/c85e5f6540936b7c6b32ecc59a0c3e95 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package json_client | |
| import ( | |
| "net" | |
| "time" | |
| ) | |
| type TimeoutConn struct { | |
| net.Conn | |
| timeout time.Duration | |
| } | |
| func NewTimeoutConn(conn net.Conn, timeout time.Duration) *TimeoutConn { | |
| return &TimeoutConn{ | |
| Conn: conn, | |
| timeout: timeout, | |
| } | |
| } | |
| func (c *TimeoutConn) Read(b []byte) (n int, err error) { | |
| c.SetReadDeadline(time.Now().Add(c.timeout)) | |
| return c.Conn.Read(b) | |
| } | |
| func (c *TimeoutConn) Write(b []byte) (n int, err error) { | |
| c.SetWriteDeadline(time.Now().Add(c.timeout)) | |
| return c.Conn.Write(b) | |
| } | |
| type dialer func(netw, addr string) (net.Conn, error) | |
| func NewTimeoutDial(readWriteTimeout, dialTimeout time.Duration) dialer { | |
| return func(netw, addr string) (net.Conn, error) { | |
| conn, err := net.DialTimeout(netw, addr, dialTimeout) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return NewTimeoutConn(conn, readWriteTimeout), nil | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package json_client | |
| import ( | |
| "io" | |
| "io/ioutil" | |
| "net" | |
| "net/http" | |
| "net/http/httptest" | |
| "testing" | |
| "time" | |
| ) | |
| func TestHttpTimeout(t *testing.T) { | |
| http.HandleFunc("/normal", func(w http.ResponseWriter, req *http.Request) { | |
| // Empirically, timeouts less than these seem to be flaky | |
| time.Sleep(100 * time.Millisecond) | |
| io.WriteString(w, "ok") | |
| }) | |
| http.HandleFunc("/timeout", func(w http.ResponseWriter, req *http.Request) { | |
| time.Sleep(250 * time.Millisecond) | |
| io.WriteString(w, "ok") | |
| }) | |
| ts := httptest.NewServer(http.DefaultServeMux) | |
| defer ts.Close() | |
| numDials := 0 | |
| client := &http.Client{ | |
| Transport: &http.Transport{ | |
| Dial: func(netw, addr string) (net.Conn, error) { | |
| t.Logf("dial to %s://%s", netw, addr) | |
| numDials++ | |
| return NewTimeoutDial(time.Millisecond*200, time.Millisecond*200)(netw, | |
| addr) | |
| }, | |
| }, | |
| } | |
| addr := ts.URL | |
| SendTestRequest(t, client, "1st", addr, "normal") | |
| SendTestRequest(t, client, "2st", addr, "normal") | |
| SendTestRequest(t, client, "3st", addr, "timeout") | |
| SendTestRequest(t, client, "4st", addr, "normal") | |
| time.Sleep(time.Millisecond * 300) | |
| SendTestRequest(t, client, "5st", addr, "normal") | |
| if numDials | |
| } | |
| func SendTestRequest(t *testing.T, client *http.Client, id, addr, path string) { | |
| req, err := http.NewRequest("GET", addr+"/"+path, nil) | |
| if err != nil { | |
| t.Fatalf("new request failed - %s", err) | |
| } | |
| req.Header.Add("Connection", "keep-alive") | |
| switch path { | |
| case "normal": | |
| if resp, err := client.Do(req); err != nil { | |
| t.Fatalf("%s request failed - %s", id, err) | |
| } else { | |
| result, err2 := ioutil.ReadAll(resp.Body) | |
| if err2 != nil { | |
| t.Fatalf("%s response read failed - %s", id, err2) | |
| } | |
| resp.Body.Close() | |
| t.Logf("%s request - %s", id, result) | |
| } | |
| case "timeout": | |
| if _, err := client.Do(req); err == nil { | |
| t.Fatalf("%s request not timeout", id) | |
| } else { | |
| t.Logf("%s request - %s", id, err) | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment