From b2f16ad821672e07fd588beecd117206d9b656fd Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Wed, 26 May 2021 10:57:39 -0700 Subject: [PATCH] Parse RPC errors as JSON content Bitcoin Core's JSON RPC server returns errors as HTTP error responses with JSON content in the body. Parse this content as JSON to give a more meaningful error. Otherwise, "binary" is given because the content contains ASCII control characters. --- lightning-block-sync/src/rpc.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/lightning-block-sync/src/rpc.rs b/lightning-block-sync/src/rpc.rs index 66570bcb..88199688 100644 --- a/lightning-block-sync/src/rpc.rs +++ b/lightning-block-sync/src/rpc.rs @@ -2,7 +2,7 @@ //! endpoint. use crate::{BlockHeaderData, BlockSource, AsyncBlockSourceResult}; -use crate::http::{HttpClient, HttpEndpoint, JsonResponse}; +use crate::http::{HttpClient, HttpEndpoint, HttpError, JsonResponse}; use bitcoin::blockdata::block::Block; use bitcoin::hash_types::BlockHash; @@ -47,8 +47,20 @@ impl RpcClient { "id": &self.id.fetch_add(1, Ordering::AcqRel).to_string() }); - let mut response = self.client.post::(&uri, &host, &self.basic_auth, content) - .await?.0; + let mut response = match self.client.post::(&uri, &host, &self.basic_auth, content).await { + Ok(JsonResponse(response)) => response, + Err(e) if e.kind() == std::io::ErrorKind::Other => { + match e.get_ref().unwrap().downcast_ref::() { + Some(http_error) => match JsonResponse::try_from(http_error.contents.clone()) { + Ok(JsonResponse(response)) => response, + Err(_) => Err(e)?, + }, + None => Err(e)?, + } + }, + Err(e) => Err(e)?, + }; + if !response.is_object() { return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "expected JSON object")); } @@ -143,7 +155,7 @@ mod tests { let response = serde_json::json!({ "error": { "code": -8, "message": "invalid parameter" }, }); - let server = HttpServer::responding_with_ok(MessageBody::Content(response)); + let server = HttpServer::responding_with_server_error(response); let mut client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap(); let invalid_block_hash = serde_json::json!("foo"); -- 2.30.2