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.

165 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! 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::<BaseMessage<'_, $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 $( /$url_param:tt )? (
$( $param_name:literal: )?
$( $param_type: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?;
match response.error_for_status() {
Ok(r) => r.json::<BaseMessage<$result>>()
.await
.map_err(|e| UError::from(e))
.map(|msg| msg.into_item()),
Err(e) => Err(UError::from(e))
}
}
}
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)
build_handler!(GET get_agents() -> Vec<Agent>);
// get jobs for client (agent_id=Uuid)
build_handler!(GET get_jobs("agent_id":Uuid) -> 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 add_jobs(Vec<JobMeta>) -> ());
// delete something (A)
build_handler!(GET del/Uuid() -> ());
/*
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>) -> ());
*/