use futures::future::BoxFuture;
use http::StatusCode;
pub struct HttpResponse {
pub status: StatusCode,
pub body: Vec<u8>,
}
pub trait HttpClient: 'static + Send + Sync {
fn get(
&self,
url: &str,
follow_redirects: bool,
) -> BoxFuture<'static, anyhow::Result<HttpResponse>>;
}
pub struct NullHttpClient;
impl HttpClient for NullHttpClient {
fn get(
&self,
_url: &str,
_follow_redirects: bool,
) -> BoxFuture<'static, anyhow::Result<HttpResponse>> {
Box::pin(async { anyhow::bail!("No HttpClient available") })
}
}
pub struct BlockedHttpClient;
impl BlockedHttpClient {
pub fn new() -> Self {
Self
}
}
impl Default for BlockedHttpClient {
fn default() -> Self {
Self
}
}
impl HttpClient for BlockedHttpClient {
fn get(
&self,
_url: &str,
_follow_redirects: bool,
) -> BoxFuture<'static, anyhow::Result<HttpResponse>> {
Box::pin(async {
Err(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
"BlockedHttpClient disallowed request",
)
.into())
})
}
}
#[cfg(any(test, feature = "test-support"))]
pub struct FakeHttpClient {
status: StatusCode,
}
#[cfg(any(test, feature = "test-support"))]
impl FakeHttpClient {
pub fn with_404_response() -> std::sync::Arc<dyn HttpClient> {
std::sync::Arc::new(Self {
status: StatusCode::NOT_FOUND,
})
}
pub fn with_200_response() -> std::sync::Arc<dyn HttpClient> {
std::sync::Arc::new(Self {
status: StatusCode::OK,
})
}
}
#[cfg(any(test, feature = "test-support"))]
impl HttpClient for FakeHttpClient {
fn get(
&self,
_url: &str,
_follow_redirects: bool,
) -> BoxFuture<'static, anyhow::Result<HttpResponse>> {
let status = self.status;
Box::pin(async move {
Ok(HttpResponse {
status,
body: Vec::new(),
})
})
}
}