use bytes::Bytes;
use serde::Deserialize;
use super::TransportError;
use crate::{
actor::simple_controller::{parse_response, PossibleResponse},
event_message::signed_event_message::{Message, Op},
oobi::{LocationScheme, Scheme},
query::query_event::SignedKelQuery,
};
mod default;
pub enum HttpReq {
Get { url: url::Url },
Post { url: url::Url, body: Vec<u8> },
}
pub struct HttpResp {
code: u16,
body: Bytes,
}
#[async_trait::async_trait]
pub trait HttpTransport {
async fn send_http_request(&self, req: HttpReq) -> Result<HttpResp, HttpTransportError>;
async fn send_message<E>(
&self,
loc: LocationScheme,
msg: Message,
) -> Result<(), TransportError<E>>
where
E: for<'de> Deserialize<'de>,
{
let url = match loc.scheme {
Scheme::Http => match &msg {
Message::Notice(_) => {
loc.url.join("process").unwrap()
}
Message::Op(op) => match op {
#[cfg(feature = "query")]
Op::Query(_) => {
panic!("can't send query in send_message");
}
#[cfg(feature = "query")]
Op::Reply(_) => {
loc.url.join("register").unwrap()
}
#[cfg(feature = "mailbox")]
Op::Exchange(_) => {
loc.url.join("forward").unwrap()
}
},
},
Scheme::Tcp => todo!(),
};
let resp = self
.send_http_request(HttpReq::Post {
url,
body: msg.to_cesr().unwrap(),
})
.await
.map_err(|_| TransportError::NetworkError)?;
match resp.code {
200..=299 => Ok(()),
_ => {
let err = serde_json::from_slice(&resp.body)
.map_err(|_| TransportError::InvalidResponse)?;
Err(TransportError::RemoteError(err))
}
}
}
#[cfg(feature = "query")]
async fn send_query<E>(
&self,
loc: LocationScheme,
qry: SignedKelQuery,
) -> Result<PossibleResponse, TransportError<E>>
where
E: for<'de> Deserialize<'de>,
{
let url = match loc.scheme {
Scheme::Http => {
loc.url.join("query").unwrap()
}
Scheme::Tcp => todo!(),
};
let resp = self
.send_http_request(HttpReq::Post {
url,
body: Message::Op(Op::Query(qry)).to_cesr().unwrap(),
})
.await
.map_err(|_| TransportError::NetworkError)?;
match resp.code {
200..=299 => {
let resp = parse_response(
&String::from_utf8(resp.body.to_vec())
.map_err(|_| TransportError::InvalidResponse)?,
)
.map_err(|_| TransportError::InvalidResponse)?;
Ok(resp)
}
_ => {
let err =
serde_json::from_slice(&resp.body).map_err(|_| TransportError::NetworkError)?;
Err(TransportError::RemoteError(err))
}
}
}
}
pub enum HttpTransportError {
NetworkError,
}