use reqwest::{Client, ClientBuilder, header};
use thiserror::Error;
pub trait HTTPService {
fn client() -> Client {
ClientBuilder::new()
.user_agent(Self::user_agent())
.build()
.expect("could not create a new HTTP client")
}
fn user_agent() -> String {
format!("{} v{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"))
}
}
pub type HTTPResult<T> = Result<T, HTTPError>;
#[derive(Debug, Error)]
pub enum HTTPError {
#[error("Error while making or processing an HTTP request: {0}")]
Request(#[from] reqwest::Error),
#[error("Error serializing POST body: {0}")]
Serialization(#[from] serde_json::Error),
#[error("Request returned HTTP {0}")]
Http(reqwest::StatusCode),
#[error("Missing Content-Type header")]
MissingContentType,
#[error("Invalid Content-Type header value: {0}")]
InvalidContentType(#[from] header::ToStrError),
#[error("Unexpected content type: {0}")]
UnexpectedContentType(String),
}
#[cfg(test)]
mod tests {
use crate::http::HTTPService;
use regex::Regex;
#[allow(dead_code)]
struct UserAgentTestService {}
impl HTTPService for UserAgentTestService {}
#[test]
fn it_returns_user_agent_with_version_number() {
let user_agent = UserAgentTestService::user_agent();
let version_re = Regex::new(r"^[a-z]+ v\d+\.\d+\.\d+(-(alpha|beta)\.\d+)?$").unwrap();
assert!(
version_re.is_match(&user_agent),
"{} does not match {}",
user_agent,
version_re,
);
}
}