Repository: thrift Updated Branches: refs/heads/master 341390c19 -> 13ac77daf
THttpClient now utilizes a package level shared HTTP client and optionally allows users of the library to specify one. Project: http://git-wip-us.apache.org/repos/asf/thrift/repo Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/13ac77da Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/13ac77da Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/13ac77da Branch: refs/heads/master Commit: 13ac77daf031443ebdfbee02bad528f53b6212eb Parents: 341390c Author: Justin Larrabee <[email protected]> Authored: Tue Nov 17 11:20:35 2015 -0700 Committer: Jens Geyer <[email protected]> Committed: Tue Nov 17 22:44:26 2015 +0100 ---------------------------------------------------------------------- lib/go/thrift/http_client.go | 70 +++++++++++++++++++++++++--------- lib/go/thrift/http_client_test.go | 56 +++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 18 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/thrift/blob/13ac77da/lib/go/thrift/http_client.go ---------------------------------------------------------------------- diff --git a/lib/go/thrift/http_client.go b/lib/go/thrift/http_client.go index bf0ed62..16f1cdd 100644 --- a/lib/go/thrift/http_client.go +++ b/lib/go/thrift/http_client.go @@ -27,7 +27,13 @@ import ( "strconv" ) +// Default to using the shared http client. Library users are +// free to change this global client or specify one through +// THttpClientOptions. +var DefaultHttpClient *http.Client = http.DefaultClient + type THttpClient struct { + client *http.Client response *http.Response url *url.URL requestBuffer *bytes.Buffer @@ -37,8 +43,9 @@ type THttpClient struct { } type THttpClientTransportFactory struct { - url string - isPost bool + options THttpClientOptions + url string + isPost bool } func (p *THttpClientTransportFactory) GetTransport(trans TTransport) TTransport { @@ -46,30 +53,43 @@ func (p *THttpClientTransportFactory) GetTransport(trans TTransport) TTransport t, ok := trans.(*THttpClient) if ok && t.url != nil { if t.requestBuffer != nil { - t2, _ := NewTHttpPostClient(t.url.String()) + t2, _ := NewTHttpPostClientWithOptions(t.url.String(), p.options) return t2 } - t2, _ := NewTHttpClient(t.url.String()) + t2, _ := NewTHttpClientWithOptions(t.url.String(), p.options) return t2 } } if p.isPost { - s, _ := NewTHttpPostClient(p.url) + s, _ := NewTHttpPostClientWithOptions(p.url, p.options) return s } - s, _ := NewTHttpClient(p.url) + s, _ := NewTHttpClientWithOptions(p.url, p.options) return s } +type THttpClientOptions struct { + // If nil, DefaultHttpClient is used + Client *http.Client +} + func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory { - return &THttpClientTransportFactory{url: url, isPost: false} + return NewTHttpClientTransportFactoryWithOptions(url, THttpClientOptions{}) +} + +func NewTHttpClientTransportFactoryWithOptions(url string, options THttpClientOptions) *THttpClientTransportFactory { + return &THttpClientTransportFactory{url: url, isPost: false, options: options} } func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory { - return &THttpClientTransportFactory{url: url, isPost: true} + return NewTHttpPostClientTransportFactoryWithOptions(url, THttpClientOptions{}) } -func NewTHttpClient(urlstr string) (TTransport, error) { +func NewTHttpPostClientTransportFactoryWithOptions(url string, options THttpClientOptions) *THttpClientTransportFactory { + return &THttpClientTransportFactory{url: url, isPost: true, options: options} +} + +func NewTHttpClientWithOptions(urlstr string, options THttpClientOptions) (TTransport, error) { parsedURL, err := url.Parse(urlstr) if err != nil { return nil, err @@ -78,16 +98,32 @@ func NewTHttpClient(urlstr string) (TTransport, error) { if err != nil { return nil, err } - return &THttpClient{response: response, url: parsedURL}, nil + client := options.Client + if client == nil { + client = DefaultHttpClient + } + return &THttpClient{client: client, response: response, url: parsedURL}, nil } -func NewTHttpPostClient(urlstr string) (TTransport, error) { +func NewTHttpClient(urlstr string) (TTransport, error) { + return NewTHttpClientWithOptions(urlstr, THttpClientOptions{}) +} + +func NewTHttpPostClientWithOptions(urlstr string, options THttpClientOptions) (TTransport, error) { parsedURL, err := url.Parse(urlstr) if err != nil { return nil, err } buf := make([]byte, 0, 1024) - return &THttpClient{url: parsedURL, requestBuffer: bytes.NewBuffer(buf), header: http.Header{}}, nil + client := options.Client + if client == nil { + client = DefaultHttpClient + } + return &THttpClient{client: client, url: parsedURL, requestBuffer: bytes.NewBuffer(buf), header: http.Header{}}, nil +} + +func NewTHttpPostClient(urlstr string) (TTransport, error) { + return NewTHttpPostClientWithOptions(urlstr, THttpClientOptions{}) } // Set the HTTP Header for this specific Thrift Transport @@ -179,14 +215,13 @@ func (p *THttpClient) Flush() error { // Close any previous response body to avoid leaking connections. p.closeResponse() - client := &http.Client{} req, err := http.NewRequest("POST", p.url.String(), p.requestBuffer) if err != nil { return NewTTransportExceptionFromError(err) } p.header.Add("Content-Type", "application/x-thrift") req.Header = p.header - response, err := client.Do(req) + response, err := p.client.Do(req) if err != nil { return NewTTransportExceptionFromError(err) } @@ -201,12 +236,11 @@ func (p *THttpClient) Flush() error { } func (p *THttpClient) RemainingBytes() (num_bytes uint64) { - len := p.response.ContentLength + len := p.response.ContentLength if len >= 0 { return uint64(len) } - + const maxSize = ^uint64(0) - return maxSize // the thruth is, we just don't know unless framed is used + return maxSize // the thruth is, we just don't know unless framed is used } - http://git-wip-us.apache.org/repos/asf/thrift/blob/13ac77da/lib/go/thrift/http_client_test.go ---------------------------------------------------------------------- diff --git a/lib/go/thrift/http_client_test.go b/lib/go/thrift/http_client_test.go index 0c2cb28..453680a 100644 --- a/lib/go/thrift/http_client_test.go +++ b/lib/go/thrift/http_client_test.go @@ -20,6 +20,7 @@ package thrift import ( + "net/http" "testing" ) @@ -48,3 +49,58 @@ func TestHttpClientHeaders(t *testing.T) { } TransportHeaderTest(t, trans, trans) } + +func TestHttpCustomClient(t *testing.T) { + l, addr := HttpClientSetupForTest(t) + if l != nil { + defer l.Close() + } + + httpTransport := &customHttpTransport{} + + trans, err := NewTHttpPostClientWithOptions("http://"+addr.String(), THttpClientOptions{ + Client: &http.Client{ + Transport: httpTransport, + }, + }) + if err != nil { + l.Close() + t.Fatalf("Unable to connect to %s: %s", addr.String(), err) + } + TransportHeaderTest(t, trans, trans) + + if !httpTransport.hit { + t.Fatalf("Custom client was not used") + } +} + +func TestHttpCustomClientPackageScope(t *testing.T) { + l, addr := HttpClientSetupForTest(t) + if l != nil { + defer l.Close() + } + httpTransport := &customHttpTransport{} + DefaultHttpClient = &http.Client{ + Transport: httpTransport, + } + + trans, err := NewTHttpPostClient("http://" + addr.String()) + if err != nil { + l.Close() + t.Fatalf("Unable to connect to %s: %s", addr.String(), err) + } + TransportHeaderTest(t, trans, trans) + + if !httpTransport.hit { + t.Fatalf("Custom client was not used") + } +} + +type customHttpTransport struct { + hit bool +} + +func (c *customHttpTransport) RoundTrip(req *http.Request) (*http.Response, error) { + c.hit = true + return http.DefaultTransport.RoundTrip(req) +}
