Files
komodo/client/periphery/rs/src/lib.rs
2024-03-20 18:14:54 -07:00

90 lines
2.2 KiB
Rust

use std::{sync::OnceLock, time::Duration};
use anyhow::Context;
use reqwest::StatusCode;
use resolver_api::HasResponse;
use serde_json::json;
use serror::deserialize_error;
pub mod api;
fn http_client() -> &'static reqwest::Client {
static PERIPHERY_HTTP_CLIENT: OnceLock<reqwest::Client> =
OnceLock::new();
PERIPHERY_HTTP_CLIENT.get_or_init(Default::default)
}
pub struct PeripheryClient {
address: String,
passkey: String,
}
impl PeripheryClient {
pub fn new(
address: impl Into<String>,
passkey: impl Into<String>,
) -> PeripheryClient {
PeripheryClient {
address: address.into(),
passkey: passkey.into(),
}
}
pub async fn request<T: HasResponse>(
&self,
request: T,
) -> anyhow::Result<T::Response> {
self.health_check().await?;
self.request_inner(request, None).await
}
pub async fn health_check(&self) -> anyhow::Result<()> {
self
.request_inner(api::GetHealth {}, Some(Duration::from_secs(1)))
.await?;
Ok(())
}
async fn request_inner<T: HasResponse>(
&self,
request: T,
timeout: Option<Duration>,
) -> anyhow::Result<T::Response> {
let req_type = T::req_type();
tracing::trace!(
"sending request | type: {req_type} | body: {request:?}"
);
let mut req = http_client()
.post(&self.address)
.json(&json!({
"type": req_type,
"params": request
}))
.header("authorization", &self.passkey);
if let Some(timeout) = timeout {
req = req.timeout(timeout);
}
let res =
req.send().await.context("failed at request to periphery")?;
let status = res.status();
tracing::debug!(
"got response | type: {req_type} | {status} | body: {res:?}",
);
if status == StatusCode::OK {
res.json().await.context(format!(
"failed to parse response to json | type: {req_type} | body: {request:?}"
))
} else {
let text = res
.text()
.await
.context("failed to convert response to text")?;
let error = deserialize_error(text)
.context(format!("request to periphery failed | {status}"));
Err(error)
}
}
}