Validate the response from InfluxDB after writing/creating a database 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
This commit is contained in:
David Bennett 2021-02-10 14:45:07 -05:00 committed by GitHub
parent 3a66b57d2c
commit c25ae5295b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 2 deletions

View File

@ -1,9 +1,11 @@
package influxdb
import (
"bytes"
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
@ -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 {
@ -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)
@ -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)

View File

@ -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 {