Improve HTTP error handling.

This modifies the code which handles failed server responses to attempt
to unmarshal the response bytes as a regular JSON-RPC response
regardless of the HTTP status code and, if that fails, return an error
that includes the status code as well as the raw response bytes.

This is being done because some JSON-RPC servers, such as Bitcoin Core,
don't follow the intended HTTP status code meanings.  For example, if
you request a block that doesn't exist, it returns a status code of 500
which is supposed to mean internal server error instead of a standard
200 status code (since the HTTP request itself was successful) along
with the JSON-RPC error response.

The result is that errors from Core will now show up as an actual
RPCError instead of an error with the raw JSON bytes.

This also has the benefit of returning the HTTP status code in the
error for real HTTP failure cases such as 401 authentication failures,
which previously would just be an empty error when used against Core
since it doesn't return the actual response along with the status code
as it should.
This commit is contained in:
Dave Collins 2016-09-16 14:40:27 -05:00
parent 6e5c0a7904
commit 2b780d16b0

View file

@ -705,15 +705,15 @@ func (c *Client) handleSendPostMessage(details *sendPostDetails) {
return
}
// Handle unsuccessful HTTP responses
if httpResponse.StatusCode < 200 || httpResponse.StatusCode >= 300 {
jReq.responseChan <- &response{err: errors.New(string(respBytes))}
return
}
// Try to unmarshal the response as a regular JSON-RPC response.
var resp rawResponse
err = json.Unmarshal(respBytes, &resp)
if err != nil {
// When the response itself isn't a valid JSON-RPC response
// return an error which includes the HTTP status code and raw
// response bytes.
err = fmt.Errorf("status code: %d, response: %q",
httpResponse.StatusCode, string(respBytes))
jReq.responseChan <- &response{err: err}
return
}