Repository: influxdata/influxdb-client-go
Pull request #181 (2020-08-14 10:06:48)

feat: Adding public HTTP service with example for custom Server API call
## Proposed Changes

- http.Service made public
- Added example for custom API call

## 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 1917ced..56558dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
 1. [#165](https://github.com/influxdata/influxdb-client-go/pull/165) Allow overriding the http.Client for the http service.
 1. [#179](https://github.com/influxdata/influxdb-client-go/pull/179) Unifying retry strategy among InfluxDB 2 clients: added exponential backoff.
 1. [#180](https://github.com/influxdata/influxdb-client-go/pull/180) Provided public logger API to enable overriding logging. It is also possible to disable logging. 
+1. [#181](https://github.com/influxdata/influxdb-client-go/pull/181) Exposed HTTP service to allow custom server API calls. Added example. 
 
 ### Bug fixes 
 1. [#175](https://github.com/influxdata/influxdb-client-go/pull/175) Fixed WriteAPIs management. Keeping single instance for each org and bucket pair.
diff --git a/internal/http/error.go b/api/http/error.go
similarity index 100%
rename from internal/http/error.go
rename to api/http/error.go
diff --git a/api/http/options.go b/api/http/options.go
index 359e976..4cf25c6 100644
--- a/api/http/options.go
+++ b/api/http/options.go
@@ -2,7 +2,6 @@
 // Use of this source code is governed by MIT
 // license that can be found in the LICENSE file.
 
-// Package http holds HTTP options
 package http
 
 import (
diff --git a/internal/http/service.go b/api/http/service.go
similarity index 71%
rename from internal/http/service.go
rename to api/http/service.go
index 7d8c3f9..0c3558b 100644
--- a/internal/http/service.go
+++ b/api/http/service.go
@@ -2,7 +2,14 @@
 // Use of this source code is governed by MIT
 // license that can be found in the LICENSE file.
 
-// Package http provides http related servicing  stuff
+// Package http provides HTTP servicing related code.
+//
+// Important type is Service which handles HTTP operations. It is internally used by library and it is not necessary to use it directly for common operations.
+// It can be useful when creating custom InfluxDB2 server API calls using generated code from the domain package, that are not yet exposed by API of this library.
+//
+// Service can be obtained from client using HTTPService() method.
+// It can be also created directly. To instantiate a Service use NewService(). Remember, the authorization param is in form "Token your-auth-token". e.g. "Token DXnd7annkGteV5Wqx9G3YjO9Ezkw87nHk8OabcyHCxF5451kdBV0Ag2cG7OmZZgCUTHroagUPdxbuoyen6TSPw==".
+//     srv := http.NewService("http://localhost:9999", "Token my-token", http.DefaultOptions())
 package http
 
 import (
@@ -15,7 +22,7 @@ import (
 	"net/url"
 	"strconv"
 
-	http2 "github.com/influxdata/influxdb-client-go/api/http"
+	http2 "github.com/influxdata/influxdb-client-go/internal/http"
 	"github.com/influxdata/influxdb-client-go/internal/log"
 )
 
@@ -25,16 +32,21 @@ type RequestCallback func(req *http.Request)
 // ResponseCallback defines function called after a successful response was received
 type ResponseCallback func(resp *http.Response) error
 
-// Service handles HTTP operations with taking care of mandatory request headers
+// Service handles HTTP operations with taking care of mandatory request headers and known errors
 type Service interface {
-	PostRequest(ctx context.Context, url string, body io.Reader, requestCallback RequestCallback, responseCallback ResponseCallback) *Error
-	GetRequest(ctx context.Context, url string, requestCallback RequestCallback, responseCallback ResponseCallback) *Error
+	// DoPostRequest sends HTTP POST request to the given url with body
+	DoPostRequest(ctx context.Context, url string, body io.Reader, requestCallback RequestCallback, responseCallback ResponseCallback) *Error
+	// DoHTTPRequest sends given HTTP request and handles response
 	DoHTTPRequest(req *http.Request, requestCallback RequestCallback, responseCallback ResponseCallback) *Error
+	// DoHTTPRequestWithResponse sends given HTTP request and returns response
 	DoHTTPRequestWithResponse(req *http.Request, requestCallback RequestCallback) (*http.Response, error)
+	// SetAuthorization sets the authorization header value
 	SetAuthorization(authorization string)
+	// Authorization returns current authorization header value
 	Authorization() string
-	HTTPClient() *http.Client
+	// ServerAPIURL returns URL to InfluxDB2 server API space
 	ServerAPIURL() string
+	// ServerURL returns URL to InfluxDB2 server
 	ServerURL() string
 }
 
@@ -47,7 +59,7 @@ type service struct {
 }
 
 // NewService creates instance of http Service with given parameters
-func NewService(serverURL, authorization string, httpOptions *http2.Options) Service {
+func NewService(serverURL, authorization string, httpOptions *Options) Service {
 	apiURL, err := url.Parse(serverURL)
 	serverAPIURL := serverURL
 	if err == nil {
@@ -80,11 +92,7 @@ func (s *service) Authorization() string {
 	return s.authorization
 }
 
-func (s *service) HTTPClient() *http.Client {
-	return s.client
-}
-
-func (s *service) PostRequest(ctx context.Context, url string, body io.Reader, requestCallback RequestCallback, responseCallback ResponseCallback) *Error {
+func (s *service) DoPostRequest(ctx context.Context, url string, body io.Reader, requestCallback RequestCallback, responseCallback ResponseCallback) *Error {
 	return s.doHTTPRequestWithURL(ctx, http.MethodPost, url, body, requestCallback, responseCallback)
 }
 
@@ -117,17 +125,13 @@ func (s *service) DoHTTPRequest(req *http.Request, requestCallback RequestCallba
 func (s *service) DoHTTPRequestWithResponse(req *http.Request, requestCallback RequestCallback) (*http.Response, error) {
 	log.Infof("HTTP %s req to %s", req.Method, req.URL.String())
 	req.Header.Set("Authorization", s.authorization)
-	req.Header.Set("User-Agent", UserAgent)
+	req.Header.Set("User-Agent", http2.UserAgent)
 	if requestCallback != nil {
 		requestCallback(req)
 	}
 	return s.client.Do(req)
 }
 
-func (s *service) GetRequest(ctx context.Context, url string, requestCallback RequestCallback, responseCallback ResponseCallback) *Error {
-	return s.doHTTPRequestWithURL(ctx, http.MethodGet, url, nil, requestCallback, responseCallback)
-}
-
 func (s *service) handleHTTPError(r *http.Response) *Error {
 	// successful status code range
 	if r.StatusCode >= 200 && r.StatusCode < 300 {
diff --git a/api/query.go b/api/query.go
index bb88435..ff4d92f 100644
--- a/api/query.go
+++ b/api/query.go
@@ -23,9 +23,9 @@ import (
 	"sync"
 	"time"
 
+	http2 "github.com/influxdata/influxdb-client-go/api/http"
 	"github.com/influxdata/influxdb-client-go/api/query"
 	"github.com/influxdata/influxdb-client-go/domain"
-	ihttp "github.com/influxdata/influxdb-client-go/internal/http"
 	"github.com/influxdata/influxdb-client-go/internal/log"
 )
 
@@ -49,7 +49,7 @@ type QueryAPI interface {
 	Query(ctx context.Context, query string) (*QueryTableResult, error)
 }
 
-func NewQueryAPI(org string, service ihttp.Service) QueryAPI {
+func NewQueryAPI(org string, service http2.Service) QueryAPI {
 	return &queryAPI{
 		org:         org,
 		httpService: service,
@@ -59,7 +59,7 @@ func NewQueryAPI(org string, service ihttp.Service) QueryAPI {
 // queryAPI implements QueryAPI interface
 type queryAPI struct {
 	org         string
-	httpService ihttp.Service
+	httpService http2.Service
 	url         string
 	lock        sync.Mutex
 }
@@ -77,7 +77,7 @@ func (q *queryAPI) QueryRaw(ctx context.Context, query string, dialect *domain.D
 	}
 	log.Debugf("Query: %s", string(qrJSON))
 	var body string
-	perror := q.httpService.PostRequest(ctx, queryURL, bytes.NewReader(qrJSON), func(req *http.Request) {
+	perror := q.httpService.DoPostRequest(ctx, queryURL, bytes.NewReader(qrJSON), func(req *http.Request) {
 		req.Header.Set("Content-Type", "application/json")
 		req.Header.Set("Accept-Encoding", "gzip")
 	},
@@ -126,7 +126,7 @@ func (q *queryAPI) Query(ctx context.Context, query string) (*QueryTableResult,
 		return nil, err
 	}
 	log.Debugf("Query: %s", string(qrJSON))
-	perror := q.httpService.PostRequest(ctx, queryURL, bytes.NewReader(qrJSON), func(req *http.Request) {
+	perror := q.httpService.DoPostRequest(ctx, queryURL, bytes.NewReader(qrJSON), func(req *http.Request) {
 		req.Header.Set("Content-Type", "application/json")
 		req.Header.Set("Accept-Encoding", "gzip")
 	},
diff --git a/api/write.go b/api/write.go
index 3165c57..7ce3195 100644
--- a/api/write.go
+++ b/api/write.go
@@ -9,8 +9,8 @@ import (
 	"strings"
 	"time"
 
+	http2 "github.com/influxdata/influxdb-client-go/api/http"
 	"github.com/influxdata/influxdb-client-go/api/write"
-	"github.com/influxdata/influxdb-client-go/internal/http"
 	"github.com/influxdata/influxdb-client-go/internal/log"
 	iwrite "github.com/influxdata/influxdb-client-go/internal/write"
 )
@@ -54,7 +54,7 @@ type writeBuffInfoReq struct {
 	writeBuffLen int
 }
 
-func NewWriteAPI(org string, bucket string, service http.Service, writeOptions *write.Options) *WriteAPIImpl {
+func NewWriteAPI(org string, bucket string, service http2.Service, writeOptions *write.Options) *WriteAPIImpl {
 	w := &WriteAPIImpl{
 		service:      iwrite.NewService(org, bucket, service, writeOptions),
 		writeBuffer:  make([]string, 0, writeOptions.BatchSize()+1),
diff --git a/api/writeAPIBlocking.go b/api/writeAPIBlocking.go
index e269a56..2f126bc 100644
--- a/api/writeAPIBlocking.go
+++ b/api/writeAPIBlocking.go
@@ -8,8 +8,8 @@ import (
 	"context"
 	"strings"
 
+	http2 "github.com/influxdata/influxdb-client-go/api/http"
 	"github.com/influxdata/influxdb-client-go/api/write"
-	"github.com/influxdata/influxdb-client-go/internal/http"
 	iwrite "github.com/influxdata/influxdb-client-go/internal/write"
 )
 
@@ -32,7 +32,7 @@ type writeAPIBlocking struct {
 }
 
 // NewWriteAPIBlocking creates new WriteAPIBlocking instance for org and bucket with underlying client
-func NewWriteAPIBlocking(org string, bucket string, service http.Service, writeOptions *write.Options) *writeAPIBlocking {
+func NewWriteAPIBlocking(org string, bucket string, service http2.Service, writeOptions *write.Options) *writeAPIBlocking {
 	return &writeAPIBlocking{service: iwrite.NewService(org, bucket, service, writeOptions), writeOptions: writeOptions}
 }
 
diff --git a/client.go b/client.go
index 6e229e5..a5e8f3e 100644
--- a/client.go
+++ b/client.go
@@ -13,8 +13,8 @@ import (
 	"sync"
 
 	"github.com/influxdata/influxdb-client-go/api"
+	"github.com/influxdata/influxdb-client-go/api/http"
 	"github.com/influxdata/influxdb-client-go/domain"
-	ihttp "github.com/influxdata/influxdb-client-go/internal/http"
 	ilog "github.com/influxdata/influxdb-client-go/internal/log"
 	"github.com/influxdata/influxdb-client-go/log"
 )
@@ -39,6 +39,8 @@ type Client interface {
 	Options() *Options
 	// ServerURL returns the url of the server url client talks to
 	ServerURL() string
+	// HTTPService returns underlying HTTP service object used by client
+	HTTPService() http.Service
 	// WriteAPI returns the asynchronous, non-blocking, Write client
 	WriteAPI(org, bucket string) api.WriteAPI
 	// WriteAPIBlocking returns the synchronous, blocking, Write client
@@ -66,7 +68,7 @@ type clientImpl struct {
 	writeAPIs     map[string]api.WriteAPI
 	syncWriteAPIs map[string]api.WriteAPIBlocking
 	lock          sync.Mutex
-	httpService   ihttp.Service
+	httpService   http.Service
 	apiClient     *domain.ClientWithResponses
 	authAPI       api.AuthorizationsAPI
 	orgAPI        api.OrganizationsAPI
@@ -93,7 +95,7 @@ func NewClientWithOptions(serverURL string, authToken string, options *Options)
 		// For subsequent path parts concatenation, url has to end with '/'
 		normServerURL = serverURL + "/"
 	}
-	service := ihttp.NewService(normServerURL, "Token "+authToken, options.httpOptions)
+	service := http.NewService(normServerURL, "Token "+authToken, options.httpOptions)
 	client := &clientImpl{
 		serverURL:     serverURL,
 		options:       options,
@@ -116,6 +118,10 @@ func (c *clientImpl) ServerURL() string {
 	return c.serverURL
 }
 
+func (c *clientImpl) HTTPService() http.Service {
+	return c.httpService
+}
+
 func (c *clientImpl) Ready(ctx context.Context) (bool, error) {
 	params := &domain.GetReadyParams{}
 	response, err := c.apiClient.GetReadyWithResponse(ctx, params)
diff --git a/domain/client.gen.go b/domain/client.gen.go
index ae31683..ee9d126 100644
--- a/domain/client.gen.go
+++ b/domain/client.gen.go
@@ -16,7 +16,7 @@ import (
 	"net/url"
 	"strings"
 
-	ihttp "github.com/influxdata/influxdb-client-go/internal/http"
+	ihttp "github.com/influxdata/influxdb-client-go/api/http"
 )
 
 // Client which conforms to the OpenAPI3 specification for this service.
diff --git a/domain/templates/imports.tmpl b/domain/templates/imports.tmpl
index 35b1df2..f9893a3 100644
--- a/domain/templates/imports.tmpl
+++ b/domain/templates/imports.tmpl
@@ -7,6 +7,6 @@ package {{.PackageName}}
 import (
 {{range .Imports}} {{ . }}
 {{end}}
-    ihttp "github.com/influxdata/influxdb-client-go/internal/http"
+    ihttp "github.com/influxdata/influxdb-client-go/api/http"
 )
 {{end}}
diff --git a/domain/utils.go b/domain/utils.go
index 106376d..2281ef7 100644
--- a/domain/utils.go
+++ b/domain/utils.go
@@ -4,10 +4,12 @@
 
 package domain
 
-import ihttp "github.com/influxdata/influxdb-client-go/internal/http"
+import (
+	"github.com/influxdata/influxdb-client-go/api/http"
+)
 
-func DomainErrorToError(error *Error, statusCode int) *ihttp.Error {
-	return &ihttp.Error{
+func DomainErrorToError(error *Error, statusCode int) *http.Error {
+	return &http.Error{
 		StatusCode: statusCode,
 		Code:       string(error.Code),
 		Message:    error.Message,
diff --git a/internal/http/userAgent.go b/internal/http/userAgent.go
index 7334661..05d2338 100644
--- a/internal/http/userAgent.go
+++ b/internal/http/userAgent.go
@@ -2,6 +2,7 @@
 // Use of this source code is governed by MIT
 // license that can be found in the LICENSE file.
 
+// Package http hold internal HTTP related stuff
 package http
 
 // UserAgent keeps once created User-Agent string
diff --git a/internal/write/service.go b/internal/write/service.go
index 8512eba..cb2b3de 100644
--- a/internal/write/service.go
+++ b/internal/write/service.go
@@ -16,9 +16,9 @@ import (
 	"sync"
 	"time"
 
+	http2 "github.com/influxdata/influxdb-client-go/api/http"
 	"github.com/influxdata/influxdb-client-go/api/write"
 	"github.com/influxdata/influxdb-client-go/internal/gzip"
-	ihttp "github.com/influxdata/influxdb-client-go/internal/http"
 	"github.com/influxdata/influxdb-client-go/internal/log"
 	lp "github.com/influxdata/line-protocol"
 )
@@ -40,7 +40,7 @@ func NewBatch(data string, retryDelay uint) *Batch {
 type Service struct {
 	org                  string
 	bucket               string
-	httpService          ihttp.Service
+	httpService          http2.Service
 	url                  string
 	lastWriteAttempt     time.Time
 	retryQueue           *queue
@@ -49,7 +49,7 @@ type Service struct {
 	retryExponentialBase uint
 }
 
-func NewService(org string, bucket string, httpService ihttp.Service, options *write.Options) *Service {
+func NewService(org string, bucket string, httpService http2.Service, options *write.Options) *Service {
 
 	retryBufferLimit := options.RetryBufferLimit() / options.BatchSize()
 	if retryBufferLimit == 0 {
@@ -137,11 +137,11 @@ func (w *Service) HandleWrite(ctx context.Context, batch *Batch) error {
 	return nil
 }
 
-func (w *Service) WriteBatch(ctx context.Context, batch *Batch) *ihttp.Error {
+func (w *Service) WriteBatch(ctx context.Context, batch *Batch) *http2.Error {
 	wURL, err := w.WriteURL()
 	if err != nil {
 		log.Errorf("%s\n", err.Error())
-		return ihttp.NewError(err)
+		return http2.NewError(err)
 	}
 	var body io.Reader
 	body = strings.NewReader(batch.batch)
@@ -149,11 +149,11 @@ func (w *Service) WriteBatch(ctx context.Context, batch *Batch) *ihttp.Error {
 	if w.writeOptions.UseGZip() {
 		body, err = gzip.CompressWithGzip(body)
 		if err != nil {
-			return ihttp.NewError(err)
+			return http2.NewError(err)
 		}
 	}
 	w.lastWriteAttempt = time.Now()
-	perror := w.httpService.PostRequest(ctx, wURL, body, func(req *http.Request) {
+	perror := w.httpService.DoPostRequest(ctx, wURL, body, func(req *http.Request) {
 		if w.writeOptions.UseGZip() {
 			req.Header.Set("Content-Encoding", "gzip")
 		}


Test patch:
diff --git a/api/http/service_test.go b/api/http/service_test.go
new file mode 100644
index 0000000..7b18184
--- /dev/null
+++ b/api/http/service_test.go
@@ -0,0 +1,18 @@
+// Copyright 2020 InfluxData, Inc. All rights reserved.
+// Use of this source code is governed by MIT
+// license that can be found in the LICENSE file.
+
+package http
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestService(t *testing.T) {
+	srv := NewService("http://localhost:9999/aa/", "Token my-token", DefaultOptions())
+	assert.Equal(t, "http://localhost:9999/aa/", srv.ServerURL())
+	assert.Equal(t, "http://localhost:9999/aa/api/v2/", srv.ServerAPIURL())
+	assert.Equal(t, "Token my-token", srv.Authorization())
+}
diff --git a/api/query_test.go b/api/query_test.go
index eadebec..198d9a4 100644
--- a/api/query_test.go
+++ b/api/query_test.go
@@ -8,11 +8,6 @@ import (
 	"context"
 	"encoding/csv"
 	"fmt"
-	http2 "github.com/influxdata/influxdb-client-go/api/http"
-	"github.com/influxdata/influxdb-client-go/api/query"
-	"github.com/influxdata/influxdb-client-go/internal/gzip"
-	ihttp "github.com/influxdata/influxdb-client-go/internal/http"
-	"github.com/stretchr/testify/assert"
 	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
@@ -20,6 +15,10 @@ import (
 	"testing"
 	"time"
 
+	http2 "github.com/influxdata/influxdb-client-go/api/http"
+	"github.com/influxdata/influxdb-client-go/api/query"
+	"github.com/influxdata/influxdb-client-go/internal/gzip"
+	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 )
 
@@ -508,7 +507,7 @@ func TestQueryRawResult(t *testing.T) {
 		}
 	}))
 	defer server.Close()
-	queryAPI := NewQueryAPI("org", ihttp.NewService(server.URL, "a", http2.DefaultOptions()))
+	queryAPI := NewQueryAPI("org", http2.NewService(server.URL, "a", http2.DefaultOptions()))
 
 	result, err := queryAPI.QueryRaw(context.Background(), "flux", nil)
 	require.Nil(t, err)
@@ -903,7 +902,7 @@ func TestFluxError(t *testing.T) {
 		}
 	}))
 	defer server.Close()
-	queryAPI := NewQueryAPI("org", ihttp.NewService(server.URL, "a", http2.DefaultOptions()))
+	queryAPI := NewQueryAPI("org", http2.NewService(server.URL, "a", http2.DefaultOptions()))
 
 	result, err := queryAPI.QueryRaw(context.Background(), "errored flux", nil)
 	assert.Equal(t, "", result)
diff --git a/api/writeAPIBlocking_test.go b/api/writeAPIBlocking_test.go
index fd7d8e9..4af3ed3 100644
--- a/api/writeAPIBlocking_test.go
+++ b/api/writeAPIBlocking_test.go
@@ -10,8 +10,8 @@ import (
 	"testing"
 	"time"
 
+	http2 "github.com/influxdata/influxdb-client-go/api/http"
 	"github.com/influxdata/influxdb-client-go/api/write"
-	"github.com/influxdata/influxdb-client-go/internal/http"
 	"github.com/influxdata/influxdb-client-go/internal/test"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
@@ -48,7 +48,7 @@ func TestWriteRecord(t *testing.T) {
 	require.Nil(t, err)
 	require.Len(t, service.Lines(), 0)
 
-	service.SetReplyError(&http.Error{Code: "invalid", Message: "data"})
+	service.SetReplyError(&http2.Error{Code: "invalid", Message: "data"})
 	err = writeAPI.WriteRecord(context.Background(), lines...)
 	require.NotNil(t, err)
 	require.Equal(t, "invalid: data", err.Error())
diff --git a/api/write_test.go b/api/write_test.go
index 013c08c..f364951 100644
--- a/api/write_test.go
+++ b/api/write_test.go
@@ -12,8 +12,8 @@ import (
 	"testing"
 	"time"
 
+	"github.com/influxdata/influxdb-client-go/api/http"
 	"github.com/influxdata/influxdb-client-go/api/write"
-	ihttp "github.com/influxdata/influxdb-client-go/internal/http"
 	"github.com/influxdata/influxdb-client-go/internal/test"
 	"github.com/influxdata/influxdb-client-go/log"
 	"github.com/stretchr/testify/assert"
@@ -160,7 +160,7 @@ func TestRetry(t *testing.T) {
 	writeAPI.waitForFlushing()
 	require.Len(t, service.Lines(), 5)
 	service.Close()
-	service.SetReplyError(&ihttp.Error{
+	service.SetReplyError(&http.Error{
 		StatusCode: 429,
 		RetryAfter: 5,
 	})
@@ -189,7 +189,7 @@ func TestRetry(t *testing.T) {
 func TestWriteError(t *testing.T) {
 	service := test.NewTestService(t, "http://localhost:8888")
 	log.Log.SetLogLevel(log.DebugLevel)
-	service.SetReplyError(&ihttp.Error{
+	service.SetReplyError(&http.Error{
 		StatusCode: 400,
 		Code:       "write",
 		Message:    "error",
diff --git a/client_e2e_test.go b/client_e2e_test.go
index 5a679d9..a2291a4 100644
--- a/client_e2e_test.go
+++ b/client_e2e_test.go
@@ -245,5 +245,40 @@ func TestQueryV1Compatibility(t *testing.T) {
 		}
 		assert.Equal(t, 42, rows)
 	}
+}
+
+func TestHTTPService(t *testing.T) {
+	client := influxdb2.NewClient("http://localhost:9999", "my-token")
+	apiClient := domain.NewClientWithResponses(client.HTTPService())
+	org, err := client.OrganizationsAPI().FindOrganizationByName(context.Background(), "my-org")
+	if err != nil {
+		//return err
+		t.Error(err)
+	}
+	taskDescription := "Example task"
+	taskFlux := `option task = {
+  name: "My task",
+  every: 1h
+}
 
+from(bucket:"my-bucket") |> range(start: -1m) |> last()`
+	taskStatus := domain.TaskStatusTypeActive
+	taskRequest := domain.TaskCreateRequest{
+		Org:         &org.Name,
+		OrgID:       org.Id,
+		Description: &taskDescription,
+		Flux:        taskFlux,
+		Status:      &taskStatus,
+	}
+	resp, err := apiClient.PostTasksWithResponse(context.Background(), &domain.PostTasksParams{}, domain.PostTasksJSONRequestBody(taskRequest))
+	if err != nil {
+		//return err
+		t.Error(err)
+	}
+	if resp.JSONDefault != nil {
+		t.Error(resp.JSONDefault.Message)
+	}
+	if assert.NotNil(t, resp.JSON201) {
+		assert.Equal(t, "My task", resp.JSON201.Name)
+	}
 }
diff --git a/client_test.go b/client_test.go
index 11c3a3d..bb54c6f 100644
--- a/client_test.go
+++ b/client_test.go
@@ -7,6 +7,7 @@ package influxdb2
 import (
 	"context"
 	"fmt"
+	http3 "github.com/influxdata/influxdb-client-go/api/http"
 	"net/http"
 	"net/http/httptest"
 	"testing"
@@ -109,7 +110,7 @@ func TestServerError429(t *testing.T) {
 	c := NewClient(server.URL, "x")
 	err := c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
 	require.NotNil(t, err)
-	perror, ok := err.(*http2.Error)
+	perror, ok := err.(*http3.Error)
 	require.True(t, ok)
 	require.NotNil(t, perror)
 	assert.Equal(t, "too many requests", perror.Code)
@@ -143,7 +144,7 @@ func TestServerErrorNonJSON(t *testing.T) {
 	c := NewClient(server.URL, "x")
 	err := c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
 	require.NotNil(t, err)
-	perror, ok := err.(*http2.Error)
+	perror, ok := err.(*http3.Error)
 	require.True(t, ok)
 	require.NotNil(t, perror)
 	assert.Equal(t, "500 Internal Server Error", perror.Code)
@@ -162,7 +163,7 @@ func TestServerErrorInflux1_8(t *testing.T) {
 	c := NewClient(server.URL, "x")
 	err := c.WriteAPIBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
 	require.NotNil(t, err)
-	perror, ok := err.(*http2.Error)
+	perror, ok := err.(*http3.Error)
 	require.True(t, ok)
 	require.NotNil(t, perror)
 	assert.Equal(t, "404 Not Found", perror.Code)
diff --git a/examples_test.go b/examples_test.go
index dd2b8c6..d371ced 100644
--- a/examples_test.go
+++ b/examples_test.go
@@ -1,7 +1,11 @@
 package influxdb2_test
 
 import (
+	"context"
+	"fmt"
+
 	"github.com/influxdata/influxdb-client-go"
+	"github.com/influxdata/influxdb-client-go/domain"
 )
 
 func ExampleClient_newClient() {
@@ -20,3 +24,37 @@ func ExampleClient_newClientWithOptions() {
 	// always close client at the end
 	defer client.Close()
 }
+
+func ExampleClient_customServerAPICall() {
+	client := influxdb2.NewClient("http://localhost:9999", "my-token")
+	apiClient := domain.NewClientWithResponses(client.HTTPService())
+	org, err := client.OrganizationsAPI().FindOrganizationByName(context.Background(), "my-org")
+	if err != nil {
+		//return err
+		panic(err)
+	}
+	taskDescription := "Example task"
+	taskFlux := `option task = {
+  name: "My task",
+  every: 1h
+}
+
+from(bucket:"my-bucket") |> range(start: -1m) |> last()`
+	taskStatus := domain.TaskStatusTypeActive
+	taskRequest := domain.TaskCreateRequest{
+		Org:         &org.Name,
+		OrgID:       org.Id,
+		Description: &taskDescription,
+		Flux:        taskFlux,
+		Status:      &taskStatus,
+	}
+	resp, err := apiClient.PostTasksWithResponse(context.Background(), &domain.PostTasksParams{}, domain.PostTasksJSONRequestBody(taskRequest))
+	if err != nil {
+		panic(err)
+	}
+	if resp.JSONDefault != nil {
+		panic(resp.JSONDefault.Message)
+	}
+	task := resp.JSON201
+	fmt.Println("Created task: ", task.Name)
+}
diff --git a/internal/test/http_service.go b/internal/test/http_service.go
index c64a1c4..a211096 100644
--- a/internal/test/http_service.go
+++ b/internal/test/http_service.go
@@ -9,14 +9,15 @@ import (
 	"compress/gzip"
 	"context"
 	"fmt"
-	ihttp "github.com/influxdata/influxdb-client-go/internal/http"
-	"github.com/stretchr/testify/assert"
 	"io"
 	"io/ioutil"
 	"net/http"
 	"strings"
 	"sync"
 	"testing"
+
+	http2 "github.com/influxdata/influxdb-client-go/api/http"
+	"github.com/stretchr/testify/assert"
 )
 
 type HTTPService struct {
@@ -26,7 +27,7 @@ type HTTPService struct {
 	t              *testing.T
 	wasGzip        bool
 	requestHandler func(c *HTTPService, url string, body io.Reader) error
-	replyError     *ihttp.Error
+	replyError     *http2.Error
 	lock           sync.Mutex
 }
 
@@ -65,13 +66,13 @@ func (t *HTTPService) Close() {
 	t.lock.Unlock()
 }
 
-func (t *HTTPService) SetReplyError(replyError *ihttp.Error) {
+func (t *HTTPService) SetReplyError(replyError *http2.Error) {
 	t.lock.Lock()
 	defer t.lock.Unlock()
 	t.replyError = replyError
 }
 
-func (t *HTTPService) ReplyError() *ihttp.Error {
+func (t *HTTPService) ReplyError() *http2.Error {
 	t.lock.Lock()
 	defer t.lock.Unlock()
 	return t.replyError
@@ -80,21 +81,21 @@ func (t *HTTPService) ReplyError() *ihttp.Error {
 func (t *HTTPService) SetAuthorization(_ string) {
 
 }
-func (t *HTTPService) GetRequest(_ context.Context, _ string, _ ihttp.RequestCallback, _ ihttp.ResponseCallback) *ihttp.Error {
+func (t *HTTPService) GetRequest(_ context.Context, _ string, _ http2.RequestCallback, _ http2.ResponseCallback) *http2.Error {
 	return nil
 }
-func (t *HTTPService) DoHTTPRequest(_ *http.Request, _ ihttp.RequestCallback, _ ihttp.ResponseCallback) *ihttp.Error {
+func (t *HTTPService) DoHTTPRequest(_ *http.Request, _ http2.RequestCallback, _ http2.ResponseCallback) *http2.Error {
 	return nil
 }
 
-func (t *HTTPService) DoHTTPRequestWithResponse(_ *http.Request, _ ihttp.RequestCallback) (*http.Response, error) {
+func (t *HTTPService) DoHTTPRequestWithResponse(_ *http.Request, _ http2.RequestCallback) (*http.Response, error) {
 	return nil, nil
 }
 
-func (t *HTTPService) PostRequest(_ context.Context, url string, body io.Reader, requestCallback ihttp.RequestCallback, _ ihttp.ResponseCallback) *ihttp.Error {
+func (t *HTTPService) DoPostRequest(_ context.Context, url string, body io.Reader, requestCallback http2.RequestCallback, _ http2.ResponseCallback) *http2.Error {
 	req, err := http.NewRequest("POST", url, nil)
 	if err != nil {
-		return ihttp.NewError(err)
+		return http2.NewError(err)
 	}
 	if requestCallback != nil {
 		requestCallback(req)
@@ -115,7 +116,7 @@ func (t *HTTPService) PostRequest(_ context.Context, url string, body io.Reader,
 	}
 
 	if err != nil {
-		return ihttp.NewError(err)
+		return http2.NewError(err)
 	} else {
 		return nil
 	}
diff --git a/internal/write/service_test.go b/internal/write/service_test.go
index bb84646..42f0e50 100644
--- a/internal/write/service_test.go
+++ b/internal/write/service_test.go
@@ -9,8 +9,8 @@ import (
 	"testing"
 	"time"
 
+	"github.com/influxdata/influxdb-client-go/api/http"
 	"github.com/influxdata/influxdb-client-go/api/write"
-	ihttp "github.com/influxdata/influxdb-client-go/internal/http"
 	"github.com/influxdata/influxdb-client-go/internal/test"
 	"github.com/influxdata/influxdb-client-go/log"
 	"github.com/stretchr/testify/assert"
@@ -63,7 +63,7 @@ func TestDefaultRetryDelay(t *testing.T) {
 	opts := write.DefaultOptions()
 	ctx := context.Background()
 	srv := NewService("my-org", "my-bucket", hs, opts)
-	hs.SetReplyError(&ihttp.Error{
+	hs.SetReplyError(&http.Error{
 		StatusCode: 502,
 	})
 	b1 := NewBatch("", opts.RetryInterval())
@@ -93,7 +93,7 @@ func TestCustomRetryDelayWithFLush(t *testing.T) {
 	opts := write.DefaultOptions().SetRetryInterval(1)
 	ctx := context.Background()
 	srv := NewService("my-org", "my-bucket", hs, opts)
-	hs.SetReplyError(&ihttp.Error{
+	hs.SetReplyError(&http.Error{
 		StatusCode: 429,
 	})
 	b1 := NewBatch("1\n", opts.RetryInterval())
@@ -136,7 +136,7 @@ func TestBufferOverwrite(t *testing.T) {
 	opts := write.DefaultOptions().SetRetryInterval(1).SetRetryBufferLimit(15000)
 	ctx := context.Background()
 	srv := NewService("my-org", "my-bucket", hs, opts)
-	hs.SetReplyError(&ihttp.Error{
+	hs.SetReplyError(&http.Error{
 		StatusCode: 429,
 	})
 	b1 := NewBatch("1\n", opts.RetryInterval())
@@ -187,7 +187,7 @@ func TestMaxRetryInterval(t *testing.T) {
 	opts := write.DefaultOptions().SetRetryInterval(1).SetMaxRetryInterval(10)
 	ctx := context.Background()
 	srv := NewService("my-org", "my-bucket", hs, opts)
-	hs.SetReplyError(&ihttp.Error{
+	hs.SetReplyError(&http.Error{
 		StatusCode: 503,
 	})
 	b1 := NewBatch("1\n", opts.RetryInterval())