use std::time::Duration;
use serde::Deserialize;
use crate::error::map_reqwest_error;
use crate::{Error, Result};
pub(crate) async fn read_success_body(
response: reqwest::Response,
timeout: Duration,
) -> Result<Vec<u8>> {
let status = response.status();
if status.as_u16() == 429 {
let retry_after = response
.headers()
.get(reqwest::header::RETRY_AFTER)
.and_then(|value| value.to_str().ok())
.and_then(|value| value.parse::<u64>().ok())
.map(Duration::from_secs);
return Err(Error::RateLimited { retry_after });
}
if !status.is_success() {
let status_code = status.as_u16();
let text = response.text().await.unwrap_or_default();
let reason = serde_json::from_str::<ApiErrorBody>(&text)
.ok()
.and_then(|body| body.reason)
.filter(|reason| !reason.is_empty())
.unwrap_or_else(|| {
if text.is_empty() {
status.to_string()
} else {
text
}
});
return Err(Error::Api {
status: status_code,
reason,
});
}
Ok(response
.bytes()
.await
.map_err(|err| map_reqwest_error(err, timeout))?
.to_vec())
}
#[derive(Debug, Deserialize)]
struct ApiErrorBody {
reason: Option<String>,
}