From b4ef14aeb291d2c837f398c19510e5873d500087 Mon Sep 17 00:00:00 2001 From: Elmer Thomas Date: Wed, 27 Jul 2016 18:12:49 -0700 Subject: [PATCH 1/2] Allow for setting a custom HTTP client --- rest.go | 32 ++++++++++++++++++++++++++------ rest_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/rest.go b/rest.go index d8aef1b..de5c2f9 100644 --- a/rest.go +++ b/rest.go @@ -11,6 +11,7 @@ import ( // Method contains the supported HTTP verbs. type Method string +// Supported HTTP verbs. const ( Get Method = "GET" Post Method = "POST" @@ -28,6 +29,16 @@ type Request struct { Body []byte } +// DefaultClient is used if no custom HTTP client is defined +var DefaultClient = &Client{HTTPClient: http.DefaultClient} + +// Client allows modification of client headers, redirect policy +// and other settings +// See https://golang.org/pkg/net/http +type Client struct { + HTTPClient *http.Client +} + // Response holds the response from an API call. type Response struct { StatusCode int // e.g. 200 @@ -59,11 +70,7 @@ func BuildRequestObject(request Request) (*http.Request, error) { // MakeRequest makes the API call. func MakeRequest(req *http.Request) (*http.Response, error) { - var Client = &http.Client{ - Transport: http.DefaultTransport, - } - res, err := Client.Do(req) - return res, err + return DefaultClient.HTTPClient.Do(req) } // BuildResponse builds the response struct. @@ -83,6 +90,19 @@ func BuildResponse(res *http.Response) (*Response, error) { // API is the main interface to the API. func API(request Request) (*Response, error) { + return DefaultClient.API(request) +} + +// The following functions enable the ability to define a +// custom HTTP Client + +// MakeRequest makes the API call. +func (c *Client) MakeRequest(req *http.Request) (*http.Response, error) { + return c.HTTPClient.Do(req) +} + +// API is the main interface to the API. +func (c *Client) API(request Request) (*Response, error) { // Add any query parameters to the URL. if len(request.QueryParams) != 0 { request.BaseURL = AddQueryParameters(request.BaseURL, request.QueryParams) @@ -95,7 +115,7 @@ func API(request Request) (*Response, error) { } // Build the HTTP client and make the request. - res, err := MakeRequest(req) + res, err := c.MakeRequest(req) if err != nil { return nil, err } diff --git a/rest_test.go b/rest_test.go index afbec8b..85be4f2 100644 --- a/rest_test.go +++ b/rest_test.go @@ -5,6 +5,7 @@ import ( "net/http" "net/http/httptest" "testing" + "time" ) func TestBuildURL(t *testing.T) { @@ -47,6 +48,7 @@ func TestBuildResponse(t *testing.T) { fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "{\"message\": \"success\"}") })) + defer fakeServer.Close() baseURL := fakeServer.URL method := Get request := Request{ @@ -74,6 +76,7 @@ func TestRest(t *testing.T) { fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "{\"message\": \"success\"}") })) + defer fakeServer.Close() host := fakeServer.URL endpoint := "/test_endpoint" baseURL := host + endpoint @@ -105,3 +108,24 @@ func TestRest(t *testing.T) { t.Errorf("Rest failed to make a valid API request. Returned error: %v", e) } } + +func TestCustomHTTPClient(t *testing.T) { + fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + time.Sleep(time.Second * 2) + fmt.Fprintln(w, "{\"message\": \"success\"}") + })) + defer fakeServer.Close() + host := fakeServer.URL + endpoint := "/test_endpoint" + baseURL := host + endpoint + method := Get + request := Request{ + Method: method, + BaseURL: baseURL, + } + customClient := &Client{&http.Client{Timeout: time.Second * 1}} + _, e := customClient.API(request) + if e == nil { + t.Error("Timeout did not trigger as expected") + } +} From 67fe53f6906bdef51a40885e5ff40ba537afb8bb Mon Sep 17 00:00:00 2001 From: Elmer Thomas Date: Thu, 28 Jul 2016 08:19:06 -0700 Subject: [PATCH 2/2] Added test to make sure we get the Timeout error --- rest_test.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/rest_test.go b/rest_test.go index 85be4f2..e8d3d03 100644 --- a/rest_test.go +++ b/rest_test.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "strings" "testing" "time" ) @@ -111,7 +112,7 @@ func TestRest(t *testing.T) { func TestCustomHTTPClient(t *testing.T) { fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - time.Sleep(time.Second * 2) + time.Sleep(time.Millisecond * 20) fmt.Fprintln(w, "{\"message\": \"success\"}") })) defer fakeServer.Close() @@ -123,9 +124,12 @@ func TestCustomHTTPClient(t *testing.T) { Method: method, BaseURL: baseURL, } - customClient := &Client{&http.Client{Timeout: time.Second * 1}} - _, e := customClient.API(request) - if e == nil { - t.Error("Timeout did not trigger as expected") + customClient := &Client{&http.Client{Timeout: time.Millisecond * 10}} + _, err := customClient.API(request) + if err == nil { + t.Error("A timeout did not trigger as expected") + } + if strings.Contains(err.Error(), "Client.Timeout exceeded while awaiting headers") == false { + t.Error("We did not receive the Timeout error") } }