Repository: influxdata/influxdb-client-go
Pull request #227 (2021-01-22 16:21:41)

feat(v3): Params, Client and New

## Proposed Changes

Adding initial implementation for Params and Client with New.

Package docs is still subject to further updates

## Checklist

- [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/README.md b/README.md
index 5339a48..01121aa 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,9 @@
 # InfluxDB Client Go
 
-InfluxDB Client Go v3 with new API. 
+[![CircleCI](https://circleci.com/gh/influxdata/influxdb-client-go/tree/v3.svg?style=svg)](https://circleci.com/gh/influxdata/influxdb-client-go/tree/v3)
+[![codecov](https://codecov.io/gh/influxdata/influxdb-client-go/branch/v3/graph/badge.svg)](https://app.codecov.io/gh/influxdata/influxdb-client-go/branch/v3)
+
+InfluxDB 2 Client Go v3 with new API. 
 
 State: under development. 
 
@@ -9,18 +12,18 @@ State: under development.
 
 | API | Endpoint | Status |
 |:----------|:----------|:----------|
-| `WritePoints()` | `/api/v2/write` | [ ] | 
-| `PointWriter` | `/api/v2/write` | [ ] |
-| `Query()` | `/api/v2/query` | [ ] |
-| `DeletePoints()` | `/api/v2/delete` | [ ] |
-| `Ready()` | `/ready` | [ ] |
-| `Health()` | `/health` | [ ] |
-| `AuthorizationAPI` | `/api/v2/authorizatons` | [ ] |
-| `BucketAPI` | `/api/v2/buckets` | [ ] |
-| `OrganizationAPI` | `/api/v2/orgs` | [ ] |
-| `UsersAPI` | `/api/v2/users` | [ ] |
-| `LabelsAPI` | `/api/v2/labels` | [ ] |
-| `TasksAPI` | `/api/v2/tasks` | [ ] |
+| `WritePoints()` | `/api/v2/write` |  | 
+| `PointWriter` | `/api/v2/write` |  |
+| `Query()` | `/api/v2/query` |  |
+| `DeletePoints()` | `/api/v2/delete` |  |
+| `Ready()` | `/ready` |  |
+| `Health()` | `/health` |  |
+| `AuthorizationAPI` | `/api/v2/authorizatons` |  |
+| `BucketAPI` | `/api/v2/buckets` |  |
+| `OrganizationAPI` | `/api/v2/orgs` |  |
+| `UsersAPI` | `/api/v2/users` |  |
+| `LabelsAPI` | `/api/v2/labels` |  |
+| `TasksAPI` | `/api/v2/tasks` |  |
 
 ## License
 
diff --git a/TODO.md b/TODO.md
index dd451a0..c2c2e3e 100644
--- a/TODO.md
+++ b/TODO.md
@@ -47,27 +47,10 @@ const DefaultBatchSize = 2000
 // Params holds the parameters for creating a new client.
 // The only mandatory fields are ServerURL and AuthToken.
 type Params struct {
-	// ServerURL holds the URL of the InfluxDB server to connect to.
-	// This must be non-empty.
-	ServerURL string
-
-	// AuthToken holds the authorization token for the API.
-	// This can be obtained through the GUI web browser interface.
-	AuthToken string
-
 	// DefaultTags specifies a set of tags that will be added to each written
 	// point. Tags specified on points override these.
 	DefaultTags map[string]string
 
-	// HTTPClient is used to make API requests.
-	//
-	// This can be used to specify a custom TLS configuration
-	// (TLSClientConfig), a custom request timeout (Timeout),
-	// or other customization as required.
-	//
-	// It HTTPClient is nil, http.DefaultClient will be used.
-	HTTPClient *http.Client
-
 	// BatchSize holds the default batch size
 	// used by PointWriter. If it's zero, DefaultBatchSize will
 	// be used. Note that this can be overridden with PointWriter.SetBatchSize.
@@ -79,11 +62,6 @@ type Params struct {
 	FlushInterval time.Duration
 }
 
-// Client implements an InfluxDB client.
-type Client struct{
-	// unexported fields
-}
-
 // WritePoints writes all the given points to the server with the
 // given organization id into the given bucket.
 // The points are written synchronously. For a higher throughput
diff --git a/go.mod b/go.mod
index 649a6cf..92d6bba 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,5 @@
 module github.com/influxdata/influxdb-client-go
 
 go 1.15
+
+require github.com/stretchr/testify v1.7.0
diff --git a/go.sum b/go.sum
index e69de29..acb88a4 100644
--- a/go.sum
+++ b/go.sum
@@ -0,0 +1,11 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/inluxclient/client.go b/inluxclient/client.go
new file mode 100644
index 0000000..fd03403
--- /dev/null
+++ b/inluxclient/client.go
@@ -0,0 +1,73 @@
+// Copyright 2021 InfluxData, Inc. All rights reserved.
+// Use of this source code is governed by MIT
+// license that can be found in the LICENSE file.
+
+// Package influxclient provides client for InfluxDB server.
+package influxclient
+
+import (
+	"errors"
+	"fmt"
+	"net/http"
+	"net/url"
+	"strings"
+)
+
+// Params holds the parameters for creating a new client.
+// The only mandatory field is ServerURL. AuthToken is also important
+// if authentication was not done outside this client.
+type Params struct {
+	// ServerURL holds the URL of the InfluxDB server to connect to.
+	// This must be non-empty. E.g. http://localhost:8086
+	ServerURL string
+
+	// AuthToken holds the authorization token for the API.
+	// This can be obtained through the GUI web browser interface.
+	AuthToken string
+
+	// HTTPClient is used to make API requests.
+	//
+	// This can be used to specify a custom TLS configuration
+	// (TLSClientConfig), a custom request timeout (Timeout),
+	// or other customization as required.
+	//
+	// It HTTPClient is nil, http.DefaultClient will be used.
+	HTTPClient *http.Client
+}
+
+// Client implements an InfluxDB client.
+type Client struct {
+	// Configuration params.
+	params Params
+	// Pre-created Authorization HTTP header value.
+	authorization string
+	// Cached base server API URL.
+	apiURL *url.URL
+}
+
+// New creates new Client with given Params, where ServerURL and AuthToken are mandatory.
+func New(params Params) (*Client, error) {
+	c := &Client{params: params}
+	if params.ServerURL == "" {
+		return nil, errors.New("empty server URL")
+	}
+	if c.params.AuthToken != "" {
+		c.authorization = "Token " + c.params.AuthToken
+	}
+	if c.params.HTTPClient == nil {
+		c.params.HTTPClient = http.DefaultClient
+	}
+
+	serverAddress := params.ServerURL
+	if !strings.HasSuffix(serverAddress, "/") {
+		// For subsequent path parts concatenation, url has to end with '/'
+		serverAddress = params.ServerURL + "/"
+	}
+	var err error
+	// Prepare server API URL
+	c.apiURL, err = url.Parse(serverAddress + "api/v2/")
+	if err != nil {
+		return nil, fmt.Errorf("error parsing server URL: %w", err)
+	}
+	return c, nil
+}


Test patch:
diff --git a/inluxclient/client_test.go b/inluxclient/client_test.go
new file mode 100644
index 0000000..40c7fde
--- /dev/null
+++ b/inluxclient/client_test.go
@@ -0,0 +1,52 @@
+package influxclient
+
+import (
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestNew(t *testing.T) {
+	_, err := New(Params{})
+	require.Error(t, err)
+	assert.Equal(t, "empty server URL", err.Error())
+
+	c, err := New(Params{ServerURL: "http://localhost:8086"})
+	require.NoError(t, err)
+	assert.Equal(t, "http://localhost:8086", c.params.ServerURL)
+	assert.Equal(t, "http://localhost:8086/api/v2/", c.apiURL.String())
+	assert.Equal(t, "", c.authorization)
+
+	_, err = New(Params{ServerURL: "localhost\n"})
+	if assert.Error(t, err) {
+		assert.True(t, strings.HasPrefix(err.Error(), "error parsing server URL:"))
+	}
+
+	c, err = New(Params{ServerURL: "http://localhost:8086", AuthToken: "my-token"})
+	require.NoError(t, err)
+	assert.Equal(t, "Token my-token", c.authorization)
+}
+
+func TestURLs(t *testing.T) {
+	urls := []struct {
+		serverURL    string
+		serverAPIURL string
+	}{
+		{"http://host:8086", "http://host:8086/api/v2/"},
+		{"http://host:8086/", "http://host:8086/api/v2/"},
+		{"http://host:8086/path", "http://host:8086/path/api/v2/"},
+		{"http://host:8086/path/", "http://host:8086/path/api/v2/"},
+		{"http://host:8086/path1/path2/path3", "http://host:8086/path1/path2/path3/api/v2/"},
+		{"http://host:8086/path1/path2/path3/", "http://host:8086/path1/path2/path3/api/v2/"},
+	}
+	for _, url := range urls {
+		t.Run(url.serverURL, func(t *testing.T) {
+			c, err := New(Params{ServerURL: url.serverURL})
+			require.NoError(t, err)
+			assert.Equal(t, url.serverURL, c.params.ServerURL)
+			assert.Equal(t, url.serverAPIURL, c.apiURL.String())
+		})
+	}
+}