Repository: influxdata/influxdb-client-go (go)

Issue:
Client is leaking TCP connections
I discovered this issue with the grafana flux datasource, but traced it back to the client. It seems TCP connections are not closed after calling `client.Close()`.

Output of the program below:
```
...
Query returned 181 rows
Open TCP connections:       59
Query returned 181 rows
Open TCP connections:       60
Query returned 181 rows
Open TCP connections:       61
Query returned 181 rows
Open TCP connections:       62
...
```

Please run this go program to see for yourself (when on linux, change .8086 to :8086 for the netstat command).
```go
package main

import (
	"context"
	"fmt"
	"log"
	"os/exec"

	influxdb2 "github.com/influxdata/influxdb-client-go"
)

func main() {
	for {
		client := influxdb2.NewClient("https://demo.factry.io:8086", "flux:xulf")
		queryAPI := client.QueryAPI("factry")

		query := `from(bucket: "simulation_tanksystem")
							|> range(start: -2h, stop:-30m)
							|> filter(fn: (r) => r._measurement == "WP1_fill_level")
							|> aggregateWindow(every: 30s, timeSrc: "_start", fn: mean, createEmpty:false)`

		// get parser flux query result
		result, err := queryAPI.Query(context.Background(), query)
		if err != nil {
			fmt.Println(err)
			return
		}
	        defer result.Close()

		count := 0
		// Use Next() to iterate over query result lines
		for result.Next() {
			// Observe when there is new grouping key producing new table
			count++
		}
		fmt.Printf("Query returned %v rows\n", count)
		if result.Err() != nil {
			fmt.Printf("Query error: %s\n", result.Err().Error())
		}

		// Ensures background processes finishes
		client.Close()

		getOpenConns()
	}
}

func getOpenConns() {
	out, err := exec.Command("sh", "-c", `netstat -atn | grep ".8086" | wc -l`).Output()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Open TCP connections: %s", out)
}

```

Pull request:
fix: Client.Close() also closes idle connections 
Closes #183 

## Proposed Changes
Client.Close() also closes idle connections if the HTTP client was created internally  (#183)

## Checklist

- [X] CHANGELOG.md updated
- [X] Rebased/mergeable
- [X] A test has been added if appropriate
- [X] Tests pass
- [X] Commit messages are in [semantic format](https://seesparkbox.com/foundry/semantic_commit_messages)



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fb0bc56..c02d82b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@
 ### Documentation
 1. [#189](https://github.com/influxdata/influxdb-client-go/pull/189) Added clarification that server URL has to be the InfluxDB server base URL to API docs and all examples.   
 
+### Bug fixes 
+1. [#192](https://github.com/influxdata/influxdb-client-go/pull/192) Client.Close() closes idle connections of internally created HTTP client 
 
 ## 2.0.1 [2020-08-14]
 ### Bug fixes 
diff --git a/api/http/options.go b/api/http/options.go
index 4cf25c6..b75a71c 100644
--- a/api/http/options.go
+++ b/api/http/options.go
@@ -15,6 +15,8 @@ import (
 type Options struct {
 	// HTTP client. Default is http.DefaultClient.
 	httpClient *http.Client
+	// Flag whether http client was created internally
+	ownClient bool
 	// TLS configuration for secure connection. Default nil
 	tlsConfig *tls.Config
 	// HTTP request timeout in sec. Default 20
@@ -37,6 +39,7 @@ func (o *Options) HTTPClient() *http.Client {
 				TLSClientConfig:     o.TLSConfig(),
 			},
 		}
+		o.ownClient = true
 	}
 	return o.httpClient
 }
@@ -49,9 +52,15 @@ func (o *Options) HTTPClient() *http.Client {
 // to be ignored.
 func (o *Options) SetHTTPClient(c *http.Client) *Options {
 	o.httpClient = c
+	o.ownClient = false
 	return o
 }
 
+// OwnHTTPClient returns true of HTTP client was created internally. False if it was set externally.
+func (o *Options) OwnHTTPClient() bool {
+	return o.ownClient
+}
+
 // TLSConfig returns tls.Config
 func (o *Options) TLSConfig() *tls.Config {
 	return o.tlsConfig
diff --git a/client.go b/client.go
index 39b3722..7657d24 100644
--- a/client.go
+++ b/client.go
@@ -33,7 +33,8 @@ type Client interface {
 	// Health returns an InfluxDB server health check result. Read the HealthCheck.Status field to get server status.
 	// Health doesn't validate authentication params.
 	Health(ctx context.Context) (*domain.HealthCheck, error)
-	// Close ensures all ongoing asynchronous write clients finish
+	// Close ensures all ongoing asynchronous write clients finish.
+	// Also closes all idle connections, in case of HTTP client was created internally.
 	Close()
 	// Options returns the options associated with client
 	Options() *Options
@@ -213,6 +214,9 @@ func (c *clientImpl) Close() {
 	for key := range c.syncWriteAPIs {
 		delete(c.syncWriteAPIs, key)
 	}
+	if c.options.HTTPOptions().OwnHTTPClient() {
+		c.options.HTTPOptions().HTTPClient().CloseIdleConnections()
+	}
 }
 
 func (c *clientImpl) QueryAPI(org string) api.QueryAPI {


Test patch:
diff --git a/api/http/options_test.go b/api/http/options_test.go
index a883781..f4186be 100644
--- a/api/http/options_test.go
+++ b/api/http/options_test.go
@@ -18,6 +18,8 @@ func TestDefaultOptions(t *testing.T) {
 	opts := http.DefaultOptions()
 	assert.Equal(t, (*tls.Config)(nil), opts.TLSConfig())
 	assert.Equal(t, uint(20), opts.HTTPRequestTimeout())
+	assert.NotNil(t, opts.HTTPClient())
+	assert.True(t, opts.OwnHTTPClient())
 }
 
 func TestOptionsSetting(t *testing.T) {
@@ -32,6 +34,7 @@ func TestOptionsSetting(t *testing.T) {
 	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)
+		assert.True(t, opts.OwnHTTPClient())
 	}
 
 	client := &nethttp.Client{
@@ -40,4 +43,5 @@ func TestOptionsSetting(t *testing.T) {
 	opts = http.DefaultOptions()
 	opts.SetHTTPClient(client)
 	assert.Equal(t, client, opts.HTTPClient())
+	assert.False(t, opts.OwnHTTPClient())
 }