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.

199 lines
5.6 KiB

4 years ago
#[allow(non_upper_case_globals)]
4 years ago
use crate::{
4 years ago
MASTER_SERVER,
MASTER_PORT,
models::*,
UResult,
4 years ago
UError,
utils::opt_to_string
4 years ago
};
use reqwest::{
Client,
Url,
4 years ago
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! build_url_by_method {
(
POST $path:tt,
pname = $($param_name:literal)?,
ptype = $($param_type:ty)?,
urlparam = $($url_param:ty)?
) => {
4 years ago
|
instance: &ClientHandler
$(, param: &$param_type)?
4 years ago
$(, url: Option<&$url_param>)?
4 years ago
| {
let request = ClientHandler::build_post(
instance,
&format!("{}/{}",
stringify!($path),
4 years ago
String::new()
$(+
&opt_to_string(url as Option<&$url_param>)
)?
)
);
request
$( .json::<BaseMessage<'_, $param_type>>(&param.as_message()) )?
}
};
(
GET $path:tt,
pname = $($param_name:literal)?,
ptype = $($param_type:ty)?,
urlparam = $($url_param:ty)?
) => {
4 years ago
|
instance: &ClientHandler
$(, param: &$param_type)?
4 years ago
$(, url: Option<&$url_param>)?
4 years ago
| {
let request = ClientHandler::build_get(
instance,
&format!("{}/{}",
stringify!($path),
4 years ago
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(
4 years ago
&self
$(, param: &$param_type)?
4 years ago
$(, 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
4 years ago
.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
4 years ago
// A - admin only
//////////////////
4 years ago
// client listing (A)
4 years ago
build_handler!(GET get_agents/Uuid() -> Vec<Agent>);
// get jobs for client
build_handler!(GET get_agent_jobs/Uuid() -> Vec<ExactJob>);
4 years ago
// get all available jobs (A)
build_handler!(GET get_jobs/Uuid() -> Vec<JobMeta>);
4 years ago
// add client to server's db
4 years ago
build_handler!(POST init(IAgent) -> ());
// create and upload job (A)
4 years ago
build_handler!(POST upload_jobs(Vec<JobMeta>) -> ());
// delete something (A)
4 years ago
build_handler!(GET del/Uuid() -> String);
4 years ago
// set jobs for client (A)
4 years ago
// POST /set_jobs/Uuid json: Vec<Uuid>
build_handler!(POST set_jobs/Uuid(Vec<Uuid>) -> ());
// report job result
build_handler!(POST report(Vec<ExactJob>) -> ());