diff --git a/CHANGELOG.md b/CHANGELOG.md index 67d0008f..534eb506 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.0 [in progress] +### Bug fixes +1. [#152](https://github.com/influxdata/influxdb-client-go/pull/152) Allow connecting to server on a URL path + ## 1.3.0 [2020-06-19] ### Features 1. [#131](https://github.com/influxdata/influxdb-client-go/pull/131) Labels API diff --git a/client.go b/client.go index 0f8719c7..537b8a1c 100644 --- a/client.go +++ b/client.go @@ -9,12 +9,13 @@ package influxdb2 import ( "context" "errors" - "github.com/influxdata/influxdb-client-go/api" - "github.com/influxdata/influxdb-client-go/internal/log" + "strings" "sync" + "github.com/influxdata/influxdb-client-go/api" "github.com/influxdata/influxdb-client-go/domain" ihttp "github.com/influxdata/influxdb-client-go/internal/http" + "github.com/influxdata/influxdb-client-go/internal/log" ) // Client provides API to communicate with InfluxDBServer. @@ -85,7 +86,12 @@ func NewClient(serverUrl string, authToken string) Client { // Authentication token can be empty in case of connecting to newly installed InfluxDB server, which has not been set up yet. // In such case Setup will set authentication token func NewClientWithOptions(serverUrl string, authToken string, options *Options) Client { - service := ihttp.NewService(serverUrl, "Token "+authToken, options.httpOptions) + normServerURL := serverUrl + if !strings.HasSuffix(normServerURL, "/") { + // For subsequent path parts concatenation, url has to end with '/' + normServerURL = serverUrl + "/" + } + service := ihttp.NewService(normServerURL, "Token "+authToken, options.httpOptions) client := &clientImpl{ serverUrl: serverUrl, options: options, diff --git a/client_test.go b/client_test.go index f5b9fdf8..13b1242d 100644 --- a/client_test.go +++ b/client_test.go @@ -6,16 +6,45 @@ package influxdb2 import ( "context" + "fmt" "net/http" "net/http/httptest" "testing" "time" http2 "github.com/influxdata/influxdb-client-go/internal/http" + iwrite "github.com/influxdata/influxdb-client-go/internal/write" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +func TestUrls(t *testing.T) { + urls := []struct { + serverURL string + serverAPIURL string + writeURLPrefix string + }{ + {"http://host:9999", "http://host:9999/api/v2/", "http://host:9999/api/v2/write"}, + {"http://host:9999/", "http://host:9999/api/v2/", "http://host:9999/api/v2/write"}, + {"http://host:9999/path", "http://host:9999/path/api/v2/", "http://host:9999/path/api/v2/write"}, + {"http://host:9999/path/", "http://host:9999/path/api/v2/", "http://host:9999/path/api/v2/write"}, + {"http://host:9999/path1/path2/path3", "http://host:9999/path1/path2/path3/api/v2/", "http://host:9999/path1/path2/path3/api/v2/write"}, + {"http://host:9999/path1/path2/path3/", "http://host:9999/path1/path2/path3/api/v2/", "http://host:9999/path1/path2/path3/api/v2/write"}, + } + for _, url := range urls { + t.Run(url.serverURL, func(t *testing.T) { + c := NewClient(url.serverURL, "x") + ci := c.(*clientImpl) + assert.Equal(t, url.serverURL, ci.serverUrl) + assert.Equal(t, url.serverAPIURL, ci.httpService.ServerApiUrl()) + ws := iwrite.NewService("org", "bucket", ci.httpService, c.Options().WriteOptions()) + wu, err := ws.WriteUrl() + require.Nil(t, err) + assert.Equal(t, url.writeURLPrefix+"?bucket=bucket&org=org&precision=ns", wu) + }) + } +} + func TestUserAgent(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(100 * time.Millisecond) @@ -42,7 +71,7 @@ func TestServerError429(t *testing.T) { w.Header().Set("Retry-After", "1") w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusTooManyRequests) - w.Write([]byte(`{"code":"too many requests", "message":"exceeded rate limit"}`)) + _, _ = w.Write([]byte(`{"code":"too many requests", "message":"exceeded rate limit"}`)) })) defer server.Close() @@ -56,11 +85,27 @@ func TestServerError429(t *testing.T) { assert.Equal(t, "exceeded rate limit", perror.Message) } +func TestServerOnPath(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/proxy/0:0/influx/api/v2/write" { + w.WriteHeader(http.StatusNoContent) + } else { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(fmt.Sprintf(`{"code":"internal server error", "message":"%s"}`, r.URL.Path))) + } + })) + + defer server.Close() + c := NewClient(server.URL+"/proxy/0:0/influx/", "x") + err := c.WriteApiBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i") + require.Nil(t, err) +} + func TestServerErrorNonJSON(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { time.Sleep(100 * time.Millisecond) w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte(`internal server error`)) + _, _ = w.Write([]byte(`internal server error`)) })) defer server.Close() @@ -79,7 +124,7 @@ func TestServerErrorInflux1_8(t *testing.T) { w.Header().Set("X-Influxdb-Error", "bruh moment") w.Header().Set("Content-Type", "application/json") w.WriteHeader(404) - w.Write([]byte(`{"error": "bruh moment"}`)) + _, _ = w.Write([]byte(`{"error": "bruh moment"}`)) })) defer server.Close() diff --git a/internal/http/service.go b/internal/http/service.go index 2f7bede9..f4457453 100644 --- a/internal/http/service.go +++ b/internal/http/service.go @@ -49,7 +49,7 @@ func NewService(serverUrl, authorization string, httpOptions *http2.Options) Ser apiUrl, err := url.Parse(serverUrl) serverApiUrl := serverUrl if err == nil { - apiUrl, err = apiUrl.Parse("/api/v2/") + apiUrl, err = apiUrl.Parse("api/v2/") if err == nil { serverApiUrl = apiUrl.String() }