-
-
Save decoomanj/c85e5f6540936b7c6b32ecc59a0c3e95 to your computer and use it in GitHub Desktop.
Revisions
-
seantalts revised this gist
Apr 25, 2014 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -3,7 +3,7 @@ package httptimeout import ( "net/http" "time" "fmt" ) type TimeoutTransport struct { -
seantalts revised this gist
Apr 25, 2014 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -37,6 +37,7 @@ func (t *TimeoutTransport) RoundTrip(req *http.Request) (*http.Response, error) select { case <-timeout:// A round trip timeout has occurred. t.Transport.CancelRequest(req) return nil, netTimeoutError{ error: fmt.Errorf("timed out after %s", t.RoundTripTimeout), } -
seantalts revised this gist
Apr 24, 2014 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ package httptimeout import ( "io" -
seantalts revised this gist
Apr 24, 2014 . 2 changed files with 55 additions and 33 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,40 +1,46 @@ package httptimeout import ( "net/http" "time" "fmt"" ) type TimeoutTransport struct { http.Transport RoundTripTimeout time.Duration } type respAndErr struct { resp *http.Response err error } type netTimeoutError struct { error } func (ne netTimeoutError) Timeout() bool { return true } // If you don't set RoundTrip on TimeoutTransport, this will always timeout at 0 func (t *TimeoutTransport) RoundTrip(req *http.Request) (*http.Response, error) { timeout := time.After(t.RoundTripTimeout) resp := make(chan respAndErr, 1) go func() { r, e := t.Transport.RoundTrip(req) resp <- respAndErr{ resp: r, err: e, } }() select { case <-timeout:// A round trip timeout has occurred. return nil, netTimeoutError{ error: fmt.Errorf("timed out after %s", t.RoundTripTimeout), } case r := <-resp: // Success! return r.resp, r.err } } 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 charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ package json_client import ( "io" @@ -22,31 +22,47 @@ func TestHttpTimeout(t *testing.T) { }) ts := httptest.NewServer(http.DefaultServeMux) defer ts.Close() numDials := 0 client := &http.Client{ Transport: &TimeoutTransport{ Transport: http.Transport{ Dial: func(netw, addr string) (net.Conn, error) { t.Logf("dial to %s://%s", netw, addr) numDials++ // For testing only. return net.Dial(netw, addr) // Regular ass dial. }, }, RoundTripTimeout: time.Millisecond * 200, }, } addr := ts.URL SendTestRequest(t, client, "1st", addr, "normal") if numDials != 1 { t.Fatalf("Should only have 1 dial at this point.") } SendTestRequest(t, client, "2st", addr, "normal") if numDials != 1 { t.Fatalf("Should only have 1 dial at this point.") } SendTestRequest(t, client, "3st", addr, "timeout") if numDials != 1 { t.Fatalf("Should only have 1 dial at this point.") } SendTestRequest(t, client, "4st", addr, "normal") if numDials != 2 { t.Fatalf("Should have our 2nd dial.") } time.Sleep(time.Millisecond * 700) SendTestRequest(t, client, "5st", addr, "normal") if numDials != 2 { t.Fatalf("Should still only have 2 dials.") } } func SendTestRequest(t *testing.T, client *http.Client, id, addr, path string) { -
seantalts revised this gist
Apr 24, 2014 . 2 changed files with 2 additions and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ package httptimeout import ( "net" 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 charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ package httptimeout import ( "io" -
seantalts revised this gist
Apr 24, 2014 . 3 changed files with 86 additions and 124 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,49 +1,40 @@ 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 charactersOriginal file line number Diff line number Diff line change @@ -1,84 +1,80 @@ 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) } } } 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 charactersOriginal file line number Diff line number Diff line change @@ -1,25 +0,0 @@ -
dmichael revised this gist
Jun 5, 2013 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -16,10 +16,10 @@ func TimeoutDialer(config *Config) func(net, addr string) (c net.Conn, err error conn, err := net.DialTimeout(netw, addr, config.ConnectTimeout) if err != nil { return nil, err } conn.SetDeadline(time.Now().Add(config.ReadWriteTimeout)) return conn, nil } } func NewTimeoutClient(args ...interface{}) *http.Client { -
dmichael revised this gist
Jun 5, 2013 . 1 changed file with 31 additions and 31 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,49 +1,49 @@ package httpclient import ( "net" "net/http" "time" ) type Config struct { ConnectTimeout time.Duration ReadWriteTimeout time.Duration } func TimeoutDialer(config *Config) func(net, addr string) (c net.Conn, err error) { return func(netw, addr string) (net.Conn, error) { conn, err := net.DialTimeout(netw, addr, config.ConnectTimeout) if err != nil { return nil, err } conn.SetDeadline(time.Now().Add(config.ReadWriteTimeout)) return conn, nil } } func NewTimeoutClient(args ...interface{}) *http.Client { // Default configuration config := &Config{ ConnectTimeout: 1 * time.Second, ReadWriteTimeout: 1 * time.Second, } // merge the default with user input if there is one if len(args) == 1 { timeout := args[0].(time.Duration) config.ConnectTimeout = timeout config.ReadWriteTimeout = timeout } if len(args) == 2 { config.ConnectTimeout = args[0].(time.Duration) config.ReadWriteTimeout = args[1].(time.Duration) } return &http.Client{ Transport: &http.Transport{ Dial: TimeoutDialer(config), }, } } -
dmichael revised this gist
Jun 5, 2013 . 2 changed files with 2 additions and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,7 @@ package httpclient import ( "net" "net/http" "time" ) 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 charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,7 @@ package httpclient import ( "io" "net" "net/http" "sync" -
dmichael revised this gist
Jun 5, 2013 . 1 changed file with 7 additions and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -2,17 +2,22 @@ This wrapper takes care of both the connection timeout and the readwrite timeout. WARNING: You must instantiate this every time you want to use it, otherwise it is likely that the timeout is reached before you actually make the call. One argument sets the connect timeout and the readwrite timeout to the same value. Other wise, 2 arguments are 1) connect and 2) readwrite It returns an *http.Client */ package main import( "httpclient" "time" ) func main() { httpClient := httpclient.NewWithTimeout(500*time.Millisecond, 1*time.Second) resp, err := httpClient.Get("http://google.com") if err != nil { fmt.Println("Rats! Google is down.") -
dmichael revised this gist
Jun 5, 2013 . 1 changed file with 20 additions and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,20 @@ /* This wrapper takes care of both the connection timeout and the readwrite timeout. WARNING: You must instantiate this every time you want to use it, otherwise it is likely that the timeout is reached before you actually make the call. */ package main import( "httpclient" "time ) func main() { httpClient := httpclient.NewWithTimeout(500*time.Millisecond) resp, err := httpClient.Get("http://google.com") if err != nil { fmt.Println("Rats! Google is down.") } } -
dmichael created this gist
Jun 5, 2013 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,49 @@ package httpclient import ( "net" "net/http" "time" ) type Config struct { ConnectTimeout time.Duration ReadWriteTimeout time.Duration } func TimeoutDialer(config *Config) func(net, addr string) (c net.Conn, err error) { return func(netw, addr string) (net.Conn, error) { conn, err := net.DialTimeout(netw, addr, config.ConnectTimeout) if err != nil { return nil, err } conn.SetDeadline(time.Now().Add(config.ReadWriteTimeout)) return conn, nil } } func NewTimeoutClient(args ...interface{}) *http.Client { // Default configuration config := &Config{ ConnectTimeout: 1 * time.Second, ReadWriteTimeout: 1 * time.Second, } // merge the default with user input if there is one if len(args) == 1 { timeout := args[0].(time.Duration) config.ConnectTimeout = timeout config.ReadWriteTimeout = timeout } if len(args) == 2 { config.ConnectTimeout = args[0].(time.Duration) config.ReadWriteTimeout = args[1].(time.Duration) } return &http.Client{ Transport: &http.Transport{ Dial: TimeoutDialer(config), }, } } 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,84 @@ package httpclient import ( "io" "net" "net/http" "sync" "testing" "time" ) var starter sync.Once var addr net.Addr func testHandler(w http.ResponseWriter, req *http.Request) { time.Sleep(500 * time.Millisecond) io.WriteString(w, "hello, world!\n") } func testDelayedHandler(w http.ResponseWriter, req *http.Request) { time.Sleep(2100 * time.Millisecond) io.WriteString(w, "hello, world ... in a bit\n") } func setupMockServer(t *testing.T) { http.HandleFunc("/test", testHandler) http.HandleFunc("/test-delayed", testDelayedHandler) ln, err := net.Listen("tcp", ":0") if err != nil { t.Fatalf("failed to listen - %s", err.Error()) } go func() { err = http.Serve(ln, nil) if err != nil { t.Fatalf("failed to start HTTP server - %s", err.Error()) } }() addr = ln.Addr() } func TestDefaultConfig(t *testing.T) { starter.Do(func() { setupMockServer(t) }) httpClient := NewTimeoutClient() req, _ := http.NewRequest("GET", "http://"+addr.String()+"/test-delayed", nil) httpClient = NewTimeoutClient() _, err := httpClient.Do(req) if err == nil { t.Fatalf("request should have timed out") } } func TestHttpClient(t *testing.T) { starter.Do(func() { setupMockServer(t) }) httpClient := NewTimeoutClient() req, _ := http.NewRequest("GET", "http://"+addr.String()+"/test", nil) resp, err := httpClient.Do(req) if err != nil { t.Fatalf("1st request failed - %s", err.Error()) } defer resp.Body.Close() connectTimeout := (250 * time.Millisecond) readWriteTimeout := (50 * time.Millisecond) httpClient = NewTimeoutClient(connectTimeout, readWriteTimeout) resp, err = httpClient.Do(req) if err == nil { t.Fatalf("2nd request should have timed out") } resp, err = httpClient.Do(req) if resp != nil { t.Fatalf("3nd request should not have timed out") } }