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 package influxdb
import ( import (
"bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -216,8 +218,19 @@ func (c *httpClient) CreateDatabase(ctx context.Context, database string) error
} }
defer resp.Body.Close() 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{} queryResp := &QueryResponse{}
dec := json.NewDecoder(resp.Body) dec := json.NewDecoder(body)
err = dec.Decode(queryResp) err = dec.Decode(queryResp)
if err != nil { if err != nil {
@ -341,8 +354,19 @@ func (c *httpClient) writeBatch(ctx context.Context, db, rp string, metrics []te
return nil 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{} writeResp := &WriteResponse{}
dec := json.NewDecoder(resp.Body) dec := json.NewDecoder(body)
var desc string var desc string
err = dec.Decode(writeResp) 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) { func makeWriteURL(loc *url.URL, db, rp, consistency string) (string, error) {
params := url.Values{} params := url.Values{}
params.Set("db", db) params.Set("db", db)

View File

@ -212,6 +212,26 @@ func TestHTTP_CreateDatabase(t *testing.T) {
w.WriteHeader(http.StatusOK) 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 { for _, tt := range tests {