|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
MASTER_SERVER,
|
|
|
|
MASTER_PORT,
|
|
|
|
models::*,
|
|
|
|
UResult,
|
|
|
|
UError,
|
|
|
|
utils::opt_to_string
|
|
|
|
};
|
|
|
|
use reqwest::{
|
|
|
|
Client,
|
|
|
|
Url,
|
|
|
|
RequestBuilder
|
|
|
|
};
|
|
|
|
use std::{
|
|
|
|
net::Ipv4Addr,
|
|
|
|
str::FromStr
|
|
|
|
};
|
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
pub struct Paths;
|
|
|
|
|
|
|
|
#[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)?
|
|
|
|
$(, url: Option<&$url_param>)?
|
|
|
|
| {
|
|
|
|
let request = ClientHandler::build_post(
|
|
|
|
instance,
|
|
|
|
&format!("{}/{}",
|
|
|
|
stringify!($path),
|
|
|
|
String::new()
|
|
|
|
$(+
|
|
|
|
&opt_to_string(url as Option<&$url_param>)
|
|
|
|
)?
|
|
|
|
)
|
|
|
|
);
|
|
|
|
request
|
|
|
|
$( .json::<BaseMessage<'_, $param_type>>(¶m.as_message()) )?
|
|
|
|
}
|
|
|
|
};
|
|
|
|
(
|
|
|
|
GET $path:tt,
|
|
|
|
pname = $($param_name:literal)?,
|
|
|
|
ptype = $($param_type:ty)?,
|
|
|
|
urlparam = $($url_param:ty)?
|
|
|
|
) => {
|
|
|
|
|
|
|
|
|
instance: &ClientHandler
|
|
|
|
$(, param: &$param_type)?
|
|
|
|
$(, url: Option<&$url_param>)?
|
|
|
|
| {
|
|
|
|
let request = ClientHandler::build_get(
|
|
|
|
instance,
|
|
|
|
&format!("{}/{}",
|
|
|
|
stringify!($path),
|
|
|
|
String::new()
|
|
|
|
$(+
|
|
|
|
&opt_to_string(url as Option<&$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 $( /$url_param:tt )? (
|
|
|
|
$( $param_name:literal: )?
|
|
|
|
$( $param_type:ty )?
|
|
|
|
) -> $result:ty
|
|
|
|
) => {
|
|
|
|
impl ClientHandler {
|
|
|
|
pub async fn $path(
|
|
|
|
&self
|
|
|
|
$(, param: &$param_type)?
|
|
|
|
$(, url_param: Option<&$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)?
|
|
|
|
$(, url_param as Option<&$url_param>)?
|
|
|
|
);
|
|
|
|
let response = request.send().await?;
|
|
|
|
let content_len = response.content_length();
|
|
|
|
let is_success = match response.error_for_status_ref() {
|
|
|
|
Ok(_) => Ok(()),
|
|
|
|
Err(e) => Err(UError::from(e))
|
|
|
|
};
|
|
|
|
match is_success {
|
|
|
|
Ok(_) => response.json::<BaseMessage<$result>>()
|
|
|
|
.await
|
|
|
|
.map(|msg| msg.into_inner())
|
|
|
|
.or_else(|e| {
|
|
|
|
match content_len {
|
|
|
|
Some(0) => Ok(Default::default()),
|
|
|
|
_ => Err(UError::from(e))
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
Err(UError::NetError(err_src, _)) => Err(
|
|
|
|
UError::NetError(
|
|
|
|
err_src,
|
|
|
|
response.text().await.unwrap()
|
|
|
|
)
|
|
|
|
),
|
|
|
|
_ => unreachable!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
// A - admin only
|
|
|
|
//////////////////
|
|
|
|
// client listing (A)
|
|
|
|
build_handler!(GET get_agents/Uuid() -> Vec<Agent>);
|
|
|
|
// get jobs for client
|
|
|
|
build_handler!(GET get_agent_jobs/Uuid() -> Vec<ExactJob>);
|
|
|
|
// get all available jobs (A)
|
|
|
|
build_handler!(GET get_jobs/Uuid() -> Vec<JobMeta>);
|
|
|
|
// add client to server's db
|
|
|
|
build_handler!(POST init(IAgent) -> ());
|
|
|
|
// create and upload job (A)
|
|
|
|
build_handler!(POST upload_jobs(Vec<JobMeta>) -> ());
|
|
|
|
// delete something (A)
|
|
|
|
build_handler!(GET del/Uuid() -> String);
|
|
|
|
// set jobs for client (A)
|
|
|
|
// POST /set_jobs/Uuid json: Vec<Uuid>
|
|
|
|
build_handler!(POST set_jobs/Uuid(Vec<Uuid>) -> ());
|
|
|
|
// report job result
|
|
|
|
build_handler!(POST report(Vec<ExactJob>) -> ());
|