bitcoin-cli: More detailed error reporting
Register a evhttp error handler to get a more detailed error message if the HTTP request fails.
This commit is contained in:
parent
fec6af7440
commit
381826dfee
1 changed files with 39 additions and 3 deletions
|
@ -116,17 +116,42 @@ static bool AppInitRPC(int argc, char* argv[])
|
|||
/** Reply structure for request_done to fill in */
|
||||
struct HTTPReply
|
||||
{
|
||||
HTTPReply(): status(0), error(-1) {}
|
||||
|
||||
int status;
|
||||
int error;
|
||||
std::string body;
|
||||
};
|
||||
|
||||
const char *http_errorstring(int code)
|
||||
{
|
||||
switch(code) {
|
||||
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
|
||||
case EVREQ_HTTP_TIMEOUT:
|
||||
return "timeout reached";
|
||||
case EVREQ_HTTP_EOF:
|
||||
return "EOF reached";
|
||||
case EVREQ_HTTP_INVALID_HEADER:
|
||||
return "error while reading header, or invalid header";
|
||||
case EVREQ_HTTP_BUFFER_ERROR:
|
||||
return "error encountered while reading or writing";
|
||||
case EVREQ_HTTP_REQUEST_CANCEL:
|
||||
return "request was canceled";
|
||||
case EVREQ_HTTP_DATA_TOO_LONG:
|
||||
return "response body is larger than allowed";
|
||||
#endif
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void http_request_done(struct evhttp_request *req, void *ctx)
|
||||
{
|
||||
HTTPReply *reply = static_cast<HTTPReply*>(ctx);
|
||||
|
||||
if (req == NULL) {
|
||||
/* If req is NULL, it means an error occurred while connecting, but
|
||||
* I'm not sure how to find out which one. We also don't really care.
|
||||
/* If req is NULL, it means an error occurred while connecting: the
|
||||
* error code will have been passed to http_error_cb.
|
||||
*/
|
||||
reply->status = 0;
|
||||
return;
|
||||
|
@ -145,6 +170,14 @@ static void http_request_done(struct evhttp_request *req, void *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
|
||||
static void http_error_cb(enum evhttp_request_error err, void *ctx)
|
||||
{
|
||||
HTTPReply *reply = static_cast<HTTPReply*>(ctx);
|
||||
reply->error = err;
|
||||
}
|
||||
#endif
|
||||
|
||||
UniValue CallRPC(const string& strMethod, const UniValue& params)
|
||||
{
|
||||
std::string host = GetArg("-rpcconnect", DEFAULT_RPCCONNECT);
|
||||
|
@ -165,6 +198,9 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
|
|||
struct evhttp_request *req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII
|
||||
if (req == NULL)
|
||||
throw runtime_error("create http request failed");
|
||||
#if LIBEVENT_VERSION_NUMBER >= 0x02010300
|
||||
evhttp_request_set_error_cb(req, http_error_cb);
|
||||
#endif
|
||||
|
||||
// Get credentials
|
||||
std::string strRPCUserColonPass;
|
||||
|
@ -204,7 +240,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
|
|||
event_base_free(base);
|
||||
|
||||
if (response.status == 0)
|
||||
throw CConnectionFailed("couldn't connect to server");
|
||||
throw CConnectionFailed(strprintf("couldn't connect to server (%d %s)", response.error, http_errorstring(response.error)));
|
||||
else if (response.status == HTTP_UNAUTHORIZED)
|
||||
throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
|
||||
else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
|
||||
|
|
Loading…
Reference in a new issue