use std::time::Duration;
use aspero_core::{Error, HttpResponse};
const MAX_MESSAGE: usize = 300;
pub(crate) fn check(resp: &HttpResponse) -> Result<(), Error> {
if resp.is_success() {
return Ok(());
}
let message = message(resp);
Err(match resp.status {
400 => Error::BadRequest(message.unwrap_or_else(|| "rejected by Crossref".into())),
401 | 403 => Error::AuthRejected { message },
404 => Error::NotFound,
429 => Error::RateLimited {
retry_after: resp
.header("retry-after")
.and_then(|v| v.trim().parse().ok())
.map(Duration::from_secs),
},
status => Error::Server { status, message },
})
}
fn message(resp: &HttpResponse) -> Option<String> {
let json: serde_json::Value = serde_json::from_slice(&resp.body).ok()?;
let text = match json.get("message")? {
serde_json::Value::String(s) => s.clone(),
serde_json::Value::Array(items) => items
.iter()
.filter_map(|i| i.get("message").and_then(|m| m.as_str()))
.collect::<Vec<_>>()
.join("; "),
_ => return None,
};
Some(match text.char_indices().nth(MAX_MESSAGE) {
Some((cut, _)) => format!("{}…", &text[..cut]),
None => text,
})
}