Repository: influxdata/influxdb-client-go
Pull request #165 (2020-07-28 17:17:02)

feat: allow overriding the http.Client for the http service
This allows overriding the http.Client for the http service. If the
client is overridden, the other options are ignored. This allows further
customization such as modifying the underlying http.Transport or the
`CheckRedirect` function.

codecov-commenter: # [Codecov](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165?src=pr&el=h1) Report
> Merging [#165](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165?src=pr&el=desc) into [master](https://codecov.io/gh/influxdata/influxdb-client-go/commit/d53b738106b7c18aae723ab789c3ced1a37d3514&el=desc) will **decrease** coverage by `0.11%`.
> The diff coverage is `78.94%`.

[![Impacted file tree graph](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165/graphs/tree.svg?width=650&height=150&src=pr&token=3644ooj300)](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #165      +/-   ##
==========================================
- Coverage   82.01%   81.89%   -0.12%     
==========================================
  Files          32       32              
  Lines        2035     2044       +9     
==========================================
+ Hits         1669     1674       +5     
- Misses        247      251       +4     
  Partials      119      119              
```


| [Impacted Files](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [options.go](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165/diff?src=pr&el=tree#diff-b3B0aW9ucy5nbw==) | `87.01% <0.00%> (-4.77%)` | :arrow_down: |
| [api/http/options.go](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165/diff?src=pr&el=tree#diff-YXBpL2h0dHAvb3B0aW9ucy5nbw==) | `100.00% <100.00%> (ø)` | |
| [internal/http/service.go](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165/diff?src=pr&el=tree#diff-aW50ZXJuYWwvaHR0cC9zZXJ2aWNlLmdv) | `74.69% <100.00%> (-2.48%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165?src=pr&el=footer). Last update [d53b738...126997f](https://codecov.io/gh/influxdata/influxdb-client-go/pull/165?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

vlastahajek: Thanks for the PR! Update also changelog, please.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 25081da..cf0b111 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,5 @@
 ## 1.5.0 [In progress]
+1. [#165](https://github.com/influxdata/influxdb-client-go/pull/165) Allow overriding the http.Client for the http service.
 
 ## 1.4.0 [2020-07-17]
 ### Breaking changes
diff --git a/api/http/options.go b/api/http/options.go
index e8377d0..63145a5 100644
--- a/api/http/options.go
+++ b/api/http/options.go
@@ -7,16 +7,51 @@ package http
 
 import (
 	"crypto/tls"
+	"net"
+	"net/http"
+	"time"
 )
 
 // Options holds http configuration properties for communicating with InfluxDB server
 type Options struct {
+	// HTTP client. Default is http.DefaultClient.
+	httpClient *http.Client
 	// TLS configuration for secure connection. Default nil
 	tlsConfig *tls.Config
 	// HTTP request timeout in sec. Default 20
 	httpRequestTimeout uint
 }
 
+// HTTPClient returns the http.Client that is configured to be used
+// for HTTP requests. It will return the one that has been set using
+// SetHTTPClient or it will construct a default client using the
+// other configured options.
+func (o *Options) HTTPClient() *http.Client {
+	if o.httpClient == nil {
+		o.httpClient = &http.Client{
+			Timeout: time.Second * time.Duration(o.HTTPRequestTimeout()),
+			Transport: &http.Transport{
+				DialContext: (&net.Dialer{
+					Timeout: 5 * time.Second,
+				}).DialContext,
+				TLSHandshakeTimeout: 5 * time.Second,
+				TLSClientConfig:     o.TLSConfig(),
+			},
+		}
+	}
+	return o.httpClient
+}
+
+// SetHTTPClient will configure the http.Client that is used
+// for HTTP requests. If set to nil, an HTTPClient will be
+// generated.
+//
+// Setting the HTTPClient will cause the other HTTP options
+// to be ignored.
+func (o *Options) SetHTTPClient(c *http.Client) {
+	o.httpClient = c
+}
+
 // TLSConfig returns tls.Config
 func (o *Options) TLSConfig() *tls.Config {
 	return o.tlsConfig
diff --git a/internal/http/service.go b/internal/http/service.go
index 34206c2..f5bac8a 100644
--- a/internal/http/service.go
+++ b/internal/http/service.go
@@ -11,11 +11,9 @@ import (
 	"io"
 	"io/ioutil"
 	"mime"
-	"net"
 	"net/http"
 	"net/url"
 	"strconv"
-	"time"
 
 	http2 "github.com/influxdata/influxdb-client-go/api/http"
 )
@@ -61,16 +59,7 @@ func NewService(serverURL, authorization string, httpOptions *http2.Options) Ser
 		serverAPIURL:  serverAPIURL,
 		serverURL:     serverURL,
 		authorization: authorization,
-		client: &http.Client{
-			Timeout: time.Second * time.Duration(httpOptions.HTTPRequestTimeout()),
-			Transport: &http.Transport{
-				DialContext: (&net.Dialer{
-					Timeout: 5 * time.Second,
-				}).DialContext,
-				TLSHandshakeTimeout: 5 * time.Second,
-				TLSClientConfig:     httpOptions.TLSConfig(),
-			},
-		},
+		client: httpOptions.HTTPClient(),
 	}
 }
 
diff --git a/options.go b/options.go
index a9096eb..efbfd11 100644
--- a/options.go
+++ b/options.go
@@ -6,9 +6,11 @@ package influxdb2
 
 import (
 	"crypto/tls"
+	nethttp "net/http"
+	"time"
+
 	"github.com/influxdata/influxdb-client-go/api/http"
 	"github.com/influxdata/influxdb-client-go/api/write"
-	"time"
 )
 
 // Options holds configuration properties for communicating with InfluxDB server
@@ -110,6 +112,24 @@ func (o *Options) SetUseGZip(useGZip bool) *Options {
 	return o
 }
 
+// HTTPClient returns the http.Client that is configured to be used
+// for HTTP requests. It will return the one that has been set using
+// SetHTTPClient or it will construct a default client using the
+// other configured options.
+func (o *Options) HTTPClient() *nethttp.Client {
+	return o.httpOptions.HTTPClient()
+}
+
+// SetHTTPClient will configure the http.Client that is used
+// for HTTP requests. If set to nil, an HTTPClient will be
+// generated.
+//
+// Setting the HTTPClient will cause the other HTTP options
+// to be ignored.
+func (o *Options) SetHTTPClient(c *nethttp.Client) {
+	o.httpOptions.SetHTTPClient(c)
+}
+
 // TLSConfig returns TLS config
 func (o *Options) TLSConfig() *tls.Config {
 	return o.HTTPOptions().TLSConfig()


Test patch:
diff --git a/api/http/options_test.go b/api/http/options_test.go
index d27388d..d8e2420 100644
--- a/api/http/options_test.go
+++ b/api/http/options_test.go
@@ -6,9 +6,12 @@ package http_test
 
 import (
 	"crypto/tls"
+	nethttp "net/http"
+	"testing"
+	"time"
+
 	"github.com/influxdata/influxdb-client-go/api/http"
 	"github.com/stretchr/testify/assert"
-	"testing"
 )
 
 func TestDefaultOptions(t *testing.T) {
@@ -26,4 +29,15 @@ func TestOptionsSetting(t *testing.T) {
 		SetHTTPRequestTimeout(50)
 	assert.Equal(t, tlsConfig, opts.TLSConfig())
 	assert.Equal(t, uint(50), opts.HTTPRequestTimeout())
+	if client := opts.HTTPClient(); assert.NotNil(t, client) {
+		assert.Equal(t, 50*time.Second, client.Timeout)
+		assert.Equal(t, tlsConfig, client.Transport.(*nethttp.Transport).TLSClientConfig)
+	}
+
+	client := &nethttp.Client{
+		Transport: &nethttp.Transport{},
+	}
+	opts = http.DefaultOptions()
+	opts.SetHTTPClient(client)
+	assert.Equal(t, client, opts.HTTPClient())
 }
diff --git a/options_test.go b/options_test.go
index 93fbe58..89d4abb 100644
--- a/options_test.go
+++ b/options_test.go
@@ -3,14 +3,15 @@ package influxdb2_test
 import (
 	"context"
 	"crypto/tls"
-	influxdb2 "github.com/influxdata/influxdb-client-go"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
 	"net/http"
 	"net/http/httptest"
 	"strings"
 	"testing"
 	"time"
+
+	influxdb2 "github.com/influxdata/influxdb-client-go"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func TestDefaultOptions(t *testing.T) {
@@ -52,8 +53,18 @@ func TestSettingsOptions(t *testing.T) {
 	assert.Equal(t, uint(7), opts.MaxRetries())
 	assert.Equal(t, tlsConfig, opts.TLSConfig())
 	assert.Equal(t, uint(50), opts.HTTPRequestTimeout())
+	if client := opts.HTTPClient(); assert.NotNil(t, client) {
+		assert.Equal(t, 50*time.Second, client.Timeout)
+		assert.Equal(t, tlsConfig, client.Transport.(*http.Transport).TLSClientConfig)
+	}
 	assert.Equal(t, uint(3), opts.LogLevel())
 	assert.Len(t, opts.WriteOptions().DefaultTags(), 1)
+
+	client := &http.Client{
+		Transport: &http.Transport{},
+	}
+	opts.SetHTTPClient(client)
+	assert.Equal(t, client, opts.HTTPClient())
 }
 
 func TestTimeout(t *testing.T) {