flabk/flabk/src/astreams/resolve.rs

68 lines
1.7 KiB
Rust

use std::{future::Future, string::FromUtf8Error};
use reqwest::{Method, StatusCode};
const LD_CONTENT_TYPE: &str = "application/ld+json";
#[derive(Debug)]
pub(crate) struct ResolveError(pub String);
impl From<reqwest::Error> for ResolveError {
fn from(err: reqwest::Error) -> Self {
Self(err.to_string())
}
}
impl From<FromUtf8Error> for ResolveError {
fn from(e: FromUtf8Error) -> Self {
Self(format!(
"invalid schema format (tried utf8): {}",
e.to_string()
))
}
}
pub(super) struct Resolver {
client: reqwest::Client,
}
impl Resolver {
pub fn new() -> Self {
Self {
client: reqwest::ClientBuilder::new().build().unwrap(),
}
}
async fn get<Out, F, Fut>(&self, iri: String, ok: F) -> Result<Out, ResolveError>
where
F: FnOnce(reqwest::Response) -> Fut,
Fut: Future<Output = Result<Out, ResolveError>>,
{
let resp = self
.client
.request(Method::GET, iri)
.header("Accept", LD_CONTENT_TYPE)
.send()
.await?;
match resp.status() {
StatusCode::OK => Ok(ok(resp).await?),
status => Err(ResolveError(format!("non-ok status: {}", status))),
}
}
pub async fn resolve_into<'a, T>(&self, iri: String) -> Result<T, ResolveError>
where
T: for<'de> serde::Deserialize<'de>,
{
Ok(self
.get(iri, |resp| async { Ok(resp.json().await?) })
.await?)
}
pub async fn resolve(&self, iri: String) -> Result<Vec<u8>, ResolveError> {
Ok(self
.get(iri, |resp| async { Ok(resp.bytes().await?.to_vec()) })
.await?)
}
}