use reqwest::{Method, RequestBuilder, Response, StatusCode};
use super::core::{PublicStorage, SessionStorage};
use super::resource::{IntoPubkyResource, IntoResourcePath};
use super::stats::ResourceStats;
use crate::{Result, cross_log, util::check_http_status};
async fn interpret_head(resp: Response) -> Result<Option<Response>> {
match resp.status() {
StatusCode::NOT_FOUND | StatusCode::GONE => {
cross_log!(debug, "HEAD request returned {}", resp.status());
Ok(None)
}
_ => {
cross_log!(debug, "HEAD request returned {}", resp.status());
Ok(Some(check_http_status(resp).await?))
}
}
}
async fn send_checked(rb: RequestBuilder) -> Result<Response> {
let resp = rb.send().await?;
cross_log!(debug, "Request completed with status {}", resp.status());
check_http_status(resp).await
}
async fn send_head(rb: RequestBuilder) -> Result<Option<Response>> {
let resp = rb.send().await?;
cross_log!(
debug,
"HEAD request completed with status {}",
resp.status()
);
interpret_head(resp).await
}
impl SessionStorage {
pub async fn get<P: IntoResourcePath>(&self, path: P) -> Result<Response> {
let rb = self.request(Method::GET, path).await?;
send_checked(rb).await
}
pub async fn exists<P: IntoResourcePath>(&self, path: P) -> Result<bool> {
let rb = self.request(Method::HEAD, path).await?;
Ok(send_head(rb).await?.is_some())
}
pub async fn stats<P: IntoResourcePath>(&self, path: P) -> Result<Option<ResourceStats>> {
let rb = self.request(Method::HEAD, path).await?;
Ok(send_head(rb)
.await?
.map(|resp| ResourceStats::from_headers(resp.headers())))
}
pub async fn put<P, B>(&self, path: P, body: B) -> Result<Response>
where
P: IntoResourcePath,
B: Into<reqwest::Body>,
{
let rb = self.request(Method::PUT, path).await?.body(body);
send_checked(rb).await
}
pub async fn delete<P: IntoResourcePath>(&self, path: P) -> Result<Response> {
let rb = self.request(Method::DELETE, path).await?;
send_checked(rb).await
}
}
impl PublicStorage {
pub async fn get<A: IntoPubkyResource>(&self, addr: A) -> Result<Response> {
let rb = self.request(Method::GET, addr).await?;
send_checked(rb).await
}
pub async fn exists<A: IntoPubkyResource>(&self, addr: A) -> Result<bool> {
let rb = self.request(Method::HEAD, addr).await?;
Ok(send_head(rb).await?.is_some())
}
pub async fn stats<A: IntoPubkyResource>(&self, addr: A) -> Result<Option<ResourceStats>> {
let rb = self.request(Method::HEAD, addr).await?;
Ok(send_head(rb)
.await?
.map(|resp| ResourceStats::from_headers(resp.headers())))
}
}