Repository: influxdata/influxdb-client-go
Pull request #138 (2020-06-24 23:56:28)

fix: errors from InfluxDB 1.8 being empty
This PR fixes errors from InfluxDB 1.8 being empty. It does this by falling back to reading the `X-Influxdb-Error`, and if that doesn't work, then `http.Error` would return the unexpected status code inside the error message.

Before PR:

![before PR screenshot](https://media.discordapp.net/attachments/287739410286379019/725485313694236682/unknown.png)

After PR:

![after PR screenshot](https://media.discordapp.net/attachments/287739410286379019/725498363772141588/unknown.png)

- [x] CHANGELOG.md updated
- [x] Rebased/mergeable
- [x] Tests pass
- [x] Sign [CLA](https://influxdata.com/community/cla/) (if not already signed)

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

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

```diff
@@            Coverage Diff             @@
##           master     #138      +/-   ##
==========================================
- Coverage   78.77%   78.66%   -0.11%     
==========================================
  Files          26       26              
  Lines        1767     1772       +5     
==========================================
+ Hits         1392     1394       +2     
- Misses        247      250       +3     
  Partials      128      128              
```


| [Impacted Files](https://codecov.io/gh/influxdata/influxdb-client-go/pull/138?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [internal/http/service.go](https://codecov.io/gh/influxdata/influxdb-client-go/pull/138/diff?src=pr&el=tree#diff-aW50ZXJuYWwvaHR0cC9zZXJ2aWNlLmdv) | `71.73% <25.00%> (-2.99%)` | :arrow_down: |
| [internal/http/error.go](https://codecov.io/gh/influxdata/influxdb-client-go/pull/138/diff?src=pr&el=tree#diff-aW50ZXJuYWwvaHR0cC9lcnJvci5nbw==) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/influxdata/influxdb-client-go/pull/138?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/138?src=pr&el=footer). Last update [81089ce...672305d](https://codecov.io/gh/influxdata/influxdb-client-go/pull/138?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d0ad635..67d0008 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 ### Features
 1. [#131](https://github.com/influxdata/influxdb-client-go/pull/131) Labels API
 1. [#136](https://github.com/influxdata/influxdb-client-go/pull/136) Possibility to specify default tags
+1. [#138](https://github.com/influxdata/influxdb-client-go/pull/138) Fix errors from InfluxDB 1.8 being empty
 
 ### Bug fixes 
 1. [#132](https://github.com/influxdata/influxdb-client-go/pull/132) Handle unsupported write type as string instead of generating panic
diff --git a/internal/http/error.go b/internal/http/error.go
index 925983f..7907ce8 100644
--- a/internal/http/error.go
+++ b/internal/http/error.go
@@ -4,7 +4,10 @@
 
 package http
 
-import "fmt"
+import (
+	"fmt"
+	"strconv"
+)
 
 // Error represent error response from InfluxDBServer or http error
 type Error struct {
@@ -17,10 +20,14 @@ type Error struct {
 
 // Error fulfils error interface
 func (e *Error) Error() string {
-	if e.Err != nil {
+	switch {
+	case e.Err != nil:
 		return e.Err.Error()
+	case e.Code != "" && e.Message != "":
+		return fmt.Sprintf("%s: %s", e.Code, e.Message)
+	default:
+		return "Unexpected status code " + strconv.Itoa(e.StatusCode)
 	}
-	return fmt.Sprintf("%s: %s", e.Code, e.Message)
 }
 
 // NewError returns newly created Error initialised with nested error and default values
diff --git a/internal/http/service.go b/internal/http/service.go
index 8756cd8..2f7bede 100644
--- a/internal/http/service.go
+++ b/internal/http/service.go
@@ -147,18 +147,18 @@ func (s *serviceImpl) handleHttpError(r *http.Response) *Error {
 
 	perror := NewError(nil)
 	perror.StatusCode = r.StatusCode
+
 	if v := r.Header.Get("Retry-After"); v != "" {
 		r, err := strconv.ParseUint(v, 10, 32)
 		if err == nil {
 			perror.RetryAfter = uint(r)
 		}
 	}
+
 	// json encoded error
 	ctype, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
 	if ctype == "application/json" {
-		err := json.NewDecoder(r.Body).Decode(perror)
-		perror.Err = err
-		return perror
+		perror.Err = json.NewDecoder(r.Body).Decode(perror)
 	} else {
 		body, err := ioutil.ReadAll(r.Body)
 		if err != nil {
@@ -178,7 +178,11 @@ func (s *serviceImpl) handleHttpError(r *http.Response) *Error {
 		case http.StatusServiceUnavailable:
 			perror.Code = "unavailable"
 			perror.Message = "service temporarily unavailable"
+		default:
+			perror.Code = r.Status
+			perror.Message = r.Header.Get("X-Influxdb-Error")
 		}
 	}
+
 	return perror
 }


Test patch:
diff --git a/client_test.go b/client_test.go
index 9888748..f5b9fdf 100644
--- a/client_test.go
+++ b/client_test.go
@@ -6,13 +6,14 @@ package influxdb2
 
 import (
 	"context"
-	http2 "github.com/influxdata/influxdb-client-go/internal/http"
-	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
 	"net/http"
 	"net/http/httptest"
 	"testing"
 	"time"
+
+	http2 "github.com/influxdata/influxdb-client-go/internal/http"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func TestUserAgent(t *testing.T) {
@@ -72,3 +73,34 @@ func TestServerErrorNonJSON(t *testing.T) {
 	assert.Equal(t, "500 Internal Server Error", perror.Code)
 	assert.Equal(t, "internal server error", perror.Message)
 }
+
+func TestServerErrorInflux1_8(t *testing.T) {
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("X-Influxdb-Error", "bruh moment")
+		w.Header().Set("Content-Type", "application/json")
+		w.WriteHeader(404)
+		w.Write([]byte(`{"error": "bruh moment"}`))
+	}))
+
+	defer server.Close()
+	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)
+	require.True(t, ok)
+	require.NotNil(t, perror)
+	assert.Equal(t, "404 Not Found", perror.Code)
+	assert.Equal(t, "bruh moment", perror.Message)
+}
+
+func TestServerErrorEmptyBody(t *testing.T) {
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(404)
+	}))
+
+	defer server.Close()
+	c := NewClient(server.URL, "x")
+	err := c.WriteApiBlocking("o", "b").WriteRecord(context.Background(), "a,a=a a=1i")
+	require.NotNil(t, err)
+	assert.Equal(t, "Unexpected status code 404", err.Error())
+}