Skip to content

Commit

Permalink
[FAB-9978] Correct CouchDB Error Return
Browse files Browse the repository at this point in the history
An error returned by CouchDB with a 500 error should
return the CouchDB error instead of the golang return code.

Change-Id: I7ecd085fbc2f87baae20db7c216419a373cdf47b
Signed-off-by: Chris Elder <[email protected]>
  • Loading branch information
Chris Elder authored and denyeart committed Jun 18, 2018
1 parent 967b506 commit 10f2925
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 22 deletions.
44 changes: 23 additions & 21 deletions core/ledger/util/couchdb/couchdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,23 @@ func (couchInstance *CouchInstance) handleRequest(method, connectURL string, dat

//if there is no golang http error and no CouchDB 500 error, then drop out of the retry
if errResp == nil && resp != nil && resp.StatusCode < 500 {
// if this is an error, then populate the couchDBReturn
if resp.StatusCode >= 400 {
//Read the response body and close it for next attempt
jsonError, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, nil, err
}
defer closeResponseBody(resp)

errorBytes := []byte(jsonError)
//Unmarshal the response
err = json.Unmarshal(errorBytes, &couchDBReturn)
if err != nil {
return nil, nil, err
}
}

break
}

Expand All @@ -1755,7 +1772,7 @@ func (couchInstance *CouchInstance) handleRequest(method, connectURL string, dat
} else {
//Read the response body and close it for next attempt
jsonError, err := ioutil.ReadAll(resp.Body)
closeResponseBody(resp)
defer closeResponseBody(resp)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -1784,7 +1801,7 @@ func (couchInstance *CouchInstance) handleRequest(method, connectURL string, dat

//if a golang http error is still present after retries are exhausted, return the error
if errResp != nil {
return nil, nil, errResp
return nil, couchDBReturn, errResp
}

//This situation should not occur according to the golang spec.
Expand All @@ -1798,27 +1815,12 @@ func (couchInstance *CouchInstance) handleRequest(method, connectURL string, dat
//set the return code for the couchDB request
couchDBReturn.StatusCode = resp.StatusCode

//check to see if the status code from couchdb is 400 or higher
//response codes 4XX and 500 will be treated as errors -
//golang error will be created from the couchDBReturn contents and both will be returned
// check to see if the status code from couchdb is 400 or higher
// response codes 4XX and 500 will be treated as errors -
// golang error will be created from the couchDBReturn contents and both will be returned
if resp.StatusCode >= 400 {
// close the response before returning error
defer closeResponseBody(resp)

//Read the response body
jsonError, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, nil, err
}

errorBytes := []byte(jsonError)

//marshal the response
err = json.Unmarshal(errorBytes, &couchDBReturn)
if err != nil {
return nil, nil, err
}

// if the status code is 400 or greater, log and return an error
logger.Debugf("Couch DB Error:%s, Status Code:%v, Reason:%s",
couchDBReturn.Error, resp.StatusCode, couchDBReturn.Reason)

Expand Down
34 changes: 33 additions & 1 deletion core/ledger/util/couchdb/couchdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1281,11 +1281,43 @@ func TestRichQuery(t *testing.T) {
testutil.AssertEquals(t, len(*queryResult), 2)

//Test query with invalid index -------------------------------------------------------------------
queryString = `{"selector":{"owner":"tom"}, "use_index":["_design/indexOwnerDoc","indexOwner"]}`
queryString = `{"selector":{"owner":"tom"}, "use_index":["indexOwnerDoc","indexOwner"]}`

_, err = db.QueryDocuments(queryString)
testutil.AssertError(t, err, fmt.Sprintf("Error should have been thrown for an invalid index"))

//Create an index definition
indexDefSize := `{"index":{"fields":[{"size":"desc"}]},"ddoc":"indexSizeSortDoc", "name":"indexSizeSortName","type":"json"}`

//Create the index
_, err = db.CreateIndex(indexDefSize)
testutil.AssertNoError(t, err, fmt.Sprintf("Error thrown while creating an index"))

//Delay for 100ms since CouchDB index list is updated async after index create/drop
time.Sleep(100 * time.Millisecond)

//Test query with valid index -------------------------------------------------------------------
queryString = `{"selector":{"size":{"$gt":0}}, "use_index":["indexSizeSortDoc","indexSizeSortName"]}`

_, err = db.QueryDocuments(queryString)
testutil.AssertNoError(t, err, fmt.Sprintf("Error when attempting to execute a query with a valid index"))

//Test query with wrong fields for a valid index -------------------------------------------------------------------
queryString = `{"selector":{"owner":{"$eq":"tom"}}, "use_index":"indexSizeSortName"}`

// no design doc specified, this should return a 400 error, indicating index not found
_, err = db.QueryDocuments(queryString)
testutil.AssertError(t, err, fmt.Sprintf("400 error should have been thrown for a missing index"))
testutil.AssertEquals(t, strings.Contains(err.Error(), "Status Code:400"), true)

//Test query with wrong fields for a valid index -------------------------------------------------------------------
queryString = `{"selector":{"owner":{"$eq":"tom"}}, "use_index":["indexSizeSortDoc","indexSizeSortName"]}`

// design doc specified, this should return a 500 error, indicating a bad match
_, err = db.QueryDocuments(queryString)
testutil.AssertError(t, err, fmt.Sprintf("500 error should have been thrown for a missing index with design doc specified"))
testutil.AssertEquals(t, strings.Contains(err.Error(), "Status Code:500"), true)

}

func testBatchBatchOperations(t *testing.T, maxRetries int) {
Expand Down

0 comments on commit 10f2925

Please sign in to comment.