Handle a response: check status, parse `ApiResponse `, unwrap data.
(
&self,
resp: reqwest::Response,
)
| 208 | |
| 209 | /// Handle a response: check status, parse `ApiResponse<T>`, unwrap data. |
| 210 | async fn handle_response<T: DeserializeOwned>( |
| 211 | &self, |
| 212 | resp: reqwest::Response, |
| 213 | ) -> Result<T, RemoteError> { |
| 214 | crate::check_min_version_header(resp.headers()); |
| 215 | let status = resp.status(); |
| 216 | let body = resp |
| 217 | .text() |
| 218 | .await |
| 219 | .map_err(|e| RemoteError::other(format!("failed to read response: {}", e)))?; |
| 220 | |
| 221 | if !status.is_success() { |
| 222 | return Err(self.parse_error_body(status.as_u16(), &body)); |
| 223 | } |
| 224 | |
| 225 | let api_resp: ApiResponse<T> = serde_json::from_str(&body).map_err(|e| { |
| 226 | // The whole body goes to the log; the error message carries a |
| 227 | // bounded preview so a large payload cannot flood the terminal. |
| 228 | log::debug!("Undeserializable response body: {}", body); |
| 229 | RemoteError::other(format!( |
| 230 | "invalid response JSON: {} (body: {})", |
| 231 | e, |
| 232 | preview(&body, BODY_PREVIEW_BYTES) |
| 233 | )) |
| 234 | })?; |
| 235 | |
| 236 | if !api_resp.success { |
| 237 | if let Some(err) = api_resp.error { |
| 238 | return Err(RemoteError::other(format!("{}: {}", err.code, err.message))); |
| 239 | } |
| 240 | return Err(RemoteError::other("request failed with no error details")); |
| 241 | } |
| 242 | |
| 243 | api_resp |
| 244 | .data |
| 245 | .ok_or_else(|| RemoteError::other("response had success=true but no data")) |
| 246 | } |
| 247 | |
| 248 | fn parse_error_body(&self, status: u16, body: &str) -> RemoteError { |
| 249 | // Try to parse as ApiResponse first. |
no test coverage detected