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.

172 lines
4.6 KiB

4 years ago
#[allow(non_upper_case_globals)]
4 years ago
use crate::{
4 years ago
MASTER_SERVER,
MASTER_PORT,
models::*,
UResult,
UError
4 years ago
};
use reqwest::{
Client,
Url,
4 years ago
Response,
RequestBuilder
4 years ago
};
use std::{
net::Ipv4Addr,
str::FromStr
};
use uuid::Uuid;
4 years ago
4 years ago
pub struct Paths;
#[macro_export]
macro_rules! get_result {
( () ) => ( |_| async Ok(()) );
( $result:ty ) => {
|response: Response| async {
response
.json::<Message<$result>>()
.await
.map(|msg| msg.into_item())
.map_err(|e| UError::from(e))
}
};
}
#[macro_export]
macro_rules! build_url_by_method {
(
POST $path:tt,
pname = $($param_name:literal)?,
ptype = $($param_type:ty)?,
urlparam = $($url_param:ty)?
) => {
|instance: &ClientHandler $(, param: &$param_type)?| {
let request = ClientHandler::build_post(
instance,
&format!("{}/{}",
stringify!($path),
String::new() $(+ stringify!($url_param))?
)
);
request
$( .json::<Message<'_, $param_type>>(&param.as_message()) )?
}
};
(
GET $path:tt,
pname = $($param_name:literal)?,
ptype = $($param_type:ty)?,
urlparam = $($url_param:ty)?
) => {
|instance: &ClientHandler $(, param: &$param_type)?| {
let request = ClientHandler::build_get(
instance,
&format!("{}/{}",
stringify!($path),
String::new() $(+ stringify!($url_param))?
)
);
request
$( .query(&[(stringify!($param_name), param.to_string())]) )?
}
};
}
// param_type and result must impl ToMsg
#[macro_export]
macro_rules! build_handler {
(
$method:tt
$path:tt(
$($param_name:literal:)?
$($param_type:ty)?
$(; $url_param:ty)?
) -> $result:ty
) => {
impl ClientHandler {
pub async fn $path(
&self $(, param: &$param_type)? $(, url_param: &$url_param)?
) -> UResult<$result> {
let request = $crate::build_url_by_method!(
$method $path,
pname = $($param_name)?, ptype = $($param_type)?, urlparam = $($url_param)?
)(self $(, param as &$param_type)? );
let response = request.send().await?;
($crate::get_result!($result)(response)).await
}
}
impl Paths {
pub const $path: &'static str = stringify!($path);
}
};
}
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)
}
}
// method basic_path(json/query param; additional_url_param) -> return value
4 years ago
// A - admin only
// client listing (A)
build_handler!(GET ls() -> ItemWrap<Vec<Agent>>);
4 years ago
// get jobs for client himself (A: id=client_id)
build_handler!(GET get_jobs() -> ItemWrap<Vec<JobMeta>>);
4 years ago
// add client to server's db
4 years ago
build_handler!(POST init(IAgent) -> RawMsg);
// create and upload job (A)
//build_handler!(POST upload_jobs)
4 years ago
// ???
/*build_handler!(POST del() -> ());
4 years ago
// set jobs for client (A)
// POST /set_jobs/Uuid json: JobMetaStorage
build_handler!(POST set_jobs(JobMetaStorage; Uuid) -> ());
// get results (A)
// GET /get_job_results?job_id=Uuid
build_handler!(GET get_job_results("job_id":Uuid) -> Vec<JobResult>);
// report job result
build_handler!(POST report(Vec<JobResult>) -> ());
*/