use crate::error::Error;
use crate::net::http;
use crate::net::http::error::HttpError;
use serde::Deserialize;
pub const API_URL: &str = "https://api.luaupm.com";
pub const MAX_ARCHIVE_BYTES: usize = 10 * 1024 * 1024;
pub const MAX_DESCRIPTION_CHARS: usize = 200;
#[derive(Deserialize)]
struct ErrorBody {
error: String,
}
pub fn publish(token: &str, archive: &[u8]) -> Result<(), Error> {
let url = format!("{API_URL}/v1/publish");
let response = ureq::post(&url)
.set("User-Agent", http::USER_AGENT)
.set("Authorization", &format!("Bearer {token}"))
.set("Content-Type", "application/gzip")
.send_bytes(archive);
match response {
Ok(_) => Ok(()),
Err(ureq::Error::Status(status, response)) => Err(Error::PublishFailed {
status,
message: error_message(status, response.into_string().ok().as_deref()),
}),
Err(other) => Err(HttpError::from(other).into()),
}
}
fn error_message(status: u16, body: Option<&str>) -> String {
body.and_then(|body| serde_json::from_str::<ErrorBody>(body).ok())
.map(|body| body.error)
.unwrap_or_else(|| format!("the registry answered HTTP {status}"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_messages_come_from_the_body_when_parsable() {
assert_eq!(
error_message(409, Some(r#"{"error":"version 1.0.0 already exists"}"#)),
"version 1.0.0 already exists"
);
assert_eq!(
error_message(502, Some("<html>Bad Gateway</html>")),
"the registry answered HTTP 502"
);
assert_eq!(error_message(500, None), "the registry answered HTTP 500");
}
}