You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

167 lines
4.3 KiB

use crate::{
MASTER_SERVER,
MASTER_PORT,
contracts::*,
UResult,
UError
};
use reqwest::{
Client,
Url,
Response,
RequestBuilder
};
use std::{
net::Ipv4Addr,
str::FromStr
};
pub struct Paths;
impl Paths {
pub const LIST: &'static str = "list";
pub const NEW: &'static str = "new";
//pub const DEL: &'static str = "del";
pub const JOB_REQ: &'static str = "job_req";
pub const JOB_ANS: &'static str = "job_ans";
}
pub struct ClientHandler {
base_url: Url,
client: Client,
password: Option<String>
}
impl ClientHandler {
pub fn new(server: Option<String>) -> Self {
let master_server = server
.map(|s| Ipv4Addr::from_str(&s).unwrap())
.unwrap_or(MASTER_SERVER);
Self {
client: Client::new(),
base_url: Url::parse(
&format!("http://{}:{}", master_server, MASTER_PORT)
).unwrap(),
password: None
}
}
pub fn password(mut self, password: String) -> ClientHandler {
self.password = Some(password);
self
}
fn set_pwd(&self, rb: RequestBuilder) -> RequestBuilder {
match &self.password {
Some(p) => rb.bearer_auth(p),
None => rb
}
}
fn build_get(&self, url: &str) -> RequestBuilder {
let rb = self.client.get(self.base_url.join(url).unwrap());
self.set_pwd(rb)
}
fn build_post(&self, url: &str) -> RequestBuilder {
let rb = self.client.post(self.base_url.join(url).unwrap());
self.set_pwd(rb)
}
pub async fn init(&self, param: &ClientInfo) -> UResult<RawMsg> {
let response: Response = self.build_post(Paths::NEW)
.json::<Message<'_, ClientInfo>>(&param.as_message())
.send()
.await?;
let msg = response
.json::<Message<RawMsg>>()
.await?;
Ok(msg.into_item().into_owned())
}
pub async fn list(&self) -> UResult<Vec<ClientInfo>> {
let response: Response = self.build_get(Paths::LIST)
.send()
.await?;
let msg = response
.json::<Message<Vec<ClientInfo>>>()
.await?;
Ok(msg.into_item().into_owned())
}
/*
pub async fn del(&self) -> UResult<()> {
self.build_post(Paths::DEL).send().await?;
Ok(())
}*/
}
#[macro_export]
macro_rules! epilogue {
( () ) => ( |_| async Ok(()) );
( $result:ty ) => {
|response: Response| async {
response
.json::<Message<$result>>()
.await
.map(|msg| msg.into_item().into_owned())
.map_err(|e| UError::from(e))
}
};
}
// build_handler![path = new, method = "post", param = ClientInfo, result = RawMsg]
// param and result must impl ToMsg
#[macro_export]
macro_rules! build_handler {
(
path = $path:tt,
method = $method:literal,
param = $($param:ty)?,
result = $result:ty
) => {
impl ClientHandler {
pub async fn $path(&self $(, param: &$param)?) -> UResult<$result> {
let builder = match $method {
"post" => ClientHandler::build_post,
"get" => ClientHandler::build_get,
_ => panic!("Method '{}' is not allowed", $method)
};
let mut request = builder(self, stringify!($path));
request = request
$(.json::<Message<'_, $param>>(&param.as_message()))?;
let response = request.send().await?;
($crate::epilogue!($result)(response)).await
}
}
impl Paths {
pub const $path: &'static str = stringify!($path);
}
};
(
path = $path:tt,
method = $method:literal
) => (
build_handler!(path = $path, method = $method, param = , result = ());
);
(
path = $path:tt,
method = $method:literal,
param = $param:ty
) => (
build_handler!(path = $path, method = $method, param = $param, result = ());
);
(
path = $path:tt,
method = $method:literal,
result = $result:ty
) => (
build_handler!(path = $path, method = $method, param = , result = $result);
);
}
build_handler!(path = del, method = "post");