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:
parent
3a66b57d2c
commit
c25ae5295b
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue