Skip to content

Commit

Permalink
Validate the response from InfluxDB after writing/creating a database…
Browse files Browse the repository at this point in the history
… to avoid json parsing panics/errors (#8775)

* Validate the response from InfluxDB after writing/creating a database to avoid json parsing panics.

* Testing windows signing - ignore

* Update config.yml

* adding signing to workflow - test

* Updated config.yml

* Updated config.yml

* Updated config.yml

* Updated config.yml

* revert circleci test changes

* Various updates
  • Loading branch information
ivorybilled authored Feb 10, 2021
1 parent 3a66b57 commit c25ae52
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 2 deletions.
49 changes: 47 additions & 2 deletions plugins/outputs/influxdb/http.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package influxdb

import (
"bytes"
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -216,8 +218,19 @@ func (c *httpClient) CreateDatabase(ctx context.Context, database string) error
}
defer resp.Body.Close()

body, err := c.validateResponse(resp.Body)

// Check for poorly formatted response (can't be decoded)
if err != nil {
return &APIError{
StatusCode: resp.StatusCode,
Title: resp.Status,
Description: "An error response was received while attempting to create the following database: " + database + ". Error: " + err.Error(),
}
}

queryResp := &QueryResponse{}
dec := json.NewDecoder(resp.Body)
dec := json.NewDecoder(body)
err = dec.Decode(queryResp)

if err != nil {
Expand Down Expand Up @@ -341,8 +354,19 @@ func (c *httpClient) writeBatch(ctx context.Context, db, rp string, metrics []te
return nil
}

body, err := c.validateResponse(resp.Body)

// Check for poorly formatted response (can't be decoded)
if err != nil {
return &APIError{
StatusCode: resp.StatusCode,
Title: resp.Status,
Description: "An error response was received while attempting to write metrics. Error: " + err.Error(),
}
}

writeResp := &WriteResponse{}
dec := json.NewDecoder(resp.Body)
dec := json.NewDecoder(body)

var desc string
err = dec.Decode(writeResp)
Expand Down Expand Up @@ -466,6 +490,27 @@ func (c *httpClient) addHeaders(req *http.Request) {
}
}

func (c *httpClient) validateResponse(response io.ReadCloser) (io.ReadCloser, error) {
bodyBytes, err := ioutil.ReadAll(response)
if err != nil {
return nil, err
}
defer response.Close()

originalResponse := ioutil.NopCloser(bytes.NewBuffer(bodyBytes))

// Empty response is valid.
if response == http.NoBody || len(bodyBytes) == 0 || bodyBytes == nil {
return originalResponse, nil
}

if valid := json.Valid(bodyBytes); !valid {
err = errors.New(string(bodyBytes))
}

return originalResponse, err
}

func makeWriteURL(loc *url.URL, db, rp, consistency string) (string, error) {
params := url.Values{}
params.Set("db", db)
Expand Down
20 changes: 20 additions & 0 deletions plugins/outputs/influxdb/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,26 @@ func TestHTTP_CreateDatabase(t *testing.T) {
w.WriteHeader(http.StatusOK)
},
},
{
name: "invalid json response is handled",
config: influxdb.HTTPConfig{
URL: u,
Database: `database`,
},
queryHandlerFunc: func(t *testing.T, w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(`invalid response`))
},
errFunc: func(t *testing.T, err error) {
expected := &influxdb.APIError{
StatusCode: 400,
Title: "400 Bad Request",
Description: "An error response was received while attempting to create the following database: database. Error: invalid response",
}

require.Equal(t, expected, err)
},
},
}

for _, tt := range tests {
Expand Down

0 comments on commit c25ae52

Please sign in to comment.