Skip to content
This repository was archived by the owner on Sep 4, 2024. It is now read-only.

Commit 090dc0f

Browse files
committed
Merge #103: minreq_http: return an HTTP error on error with no JSON in body
66fb441 minreq_http: return an HTTP error on error with no JSON in body (Antoine Poinsot) Pull request description: It is useful for downstream users to be matching on errors that do not contain a valid JSONRPC error in the HTTP response body. One instance is if the HTTP server work queue depth is exceeded, as they probably want to retry the request later. On such error we would return a JSON deserialization error, without exposing neither the HTTP status code nor the body of the response. This made it impossible to detect such transient errors. Instead, introduce a new HttpError variant that gets returned when the requested is responded to by an error that does not contain valid JSON in its body. See also: #94 (comment). ACKs for top commit: apoelstra: ACK 66fb441 Tree-SHA512: 76c831331c3b84e2f4319d62828b18574fd6af39a49c98d06c0c5a9c7833c828c9e02522b635a52f289e149cfc0a1abc160ac18d5edaf36114126186d39f4e0b
2 parents b0e80dc + 66fb441 commit 090dc0f

File tree

1 file changed

+40
-3
lines changed

1 file changed

+40
-3
lines changed

src/http/minreq_http.rs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,23 @@ impl MinreqHttpTransport {
6666
.with_json(&req)?,
6767
};
6868

69+
// Send the request and parse the response. If the response is an error that does not
70+
// contain valid JSON in its body (for instance if the bitcoind HTTP server work queue
71+
// depth is exceeded), return the raw HTTP error so users can match against it.
6972
let resp = req.send()?;
70-
let json = resp.json()?;
71-
Ok(json)
73+
match resp.json() {
74+
Ok(json) => Ok(json),
75+
Err(minreq_err) => {
76+
if resp.status_code != 200 {
77+
Err(Error::Http(HttpError {
78+
status_code: resp.status_code,
79+
body: resp.as_str().unwrap_or("").to_string(),
80+
}))
81+
} else {
82+
Err(Error::Minreq(minreq_err))
83+
}
84+
}
85+
}
7286
}
7387
}
7488

@@ -156,20 +170,42 @@ impl Default for Builder {
156170
}
157171
}
158172

159-
/// Error that can happen when sending requests.
173+
/// An HTTP error.
174+
#[derive(Debug)]
175+
pub struct HttpError {
176+
/// Status code of the error response.
177+
pub status_code: i32,
178+
/// Raw body of the error response.
179+
pub body: String,
180+
}
181+
182+
impl fmt::Display for HttpError {
183+
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
184+
write!(f, "status: {}, body: {}", self.status_code, self.body)
185+
}
186+
}
187+
188+
impl error::Error for HttpError {}
189+
190+
/// Error that can happen when sending requests. In case of error, a JSON error is returned if the
191+
/// body of the response could be parsed as such. Otherwise, an HTTP error is returned containing
192+
/// the status code and the raw body.
160193
#[derive(Debug)]
161194
pub enum Error {
162195
/// JSON parsing error.
163196
Json(serde_json::Error),
164197
/// Minreq error.
165198
Minreq(minreq::Error),
199+
/// HTTP error that does not contain valid JSON as body.
200+
Http(HttpError),
166201
}
167202

168203
impl fmt::Display for Error {
169204
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
170205
match *self {
171206
Error::Json(ref e) => write!(f, "parsing JSON failed: {}", e),
172207
Error::Minreq(ref e) => write!(f, "minreq: {}", e),
208+
Error::Http(ref e) => write!(f, "http ({})", e),
173209
}
174210
}
175211
}
@@ -181,6 +217,7 @@ impl error::Error for Error {
181217
match *self {
182218
Json(ref e) => Some(e),
183219
Minreq(ref e) => Some(e),
220+
Http(ref e) => Some(e),
184221
}
185222
}
186223
}

0 commit comments

Comments
 (0)