use crate::{HeapMap, MuxNode, RequestError};
use gluescript::{constants, RequestBodyType};
use jsonpath_rust::JsonPathFinder;
use reqwest::Client;
use serde_json::Value;
use std::{error::Error, sync::Arc};
pub async fn execute_node(node: MuxNode, heap: HeapMap, log_info: bool) -> Result<(), String> {
let mut w_node = node.lock().unwrap();
match w_node.resolve_predicate() {
Err(x) => return Err(x),
_ => (),
};
if log_info {
w_node.print_info();
}
let method = String::from(&w_node.method);
drop(w_node);
let result = match method.as_str() {
constants::REQ => {
let r_node = node.lock().unwrap();
String::from(
heap.lock()
.unwrap()
.get(&r_node.url)
.expect(constants::ERR_UNRESOLVED_VAR),
)
}
_ => match send_http_request(Arc::clone(&node)).await {
Err(x) => return Err(x.to_string()),
Ok(x) => x,
},
};
let mut w_node = node.lock().unwrap();
let is_root = w_node.depth == 0;
w_node.result = match get_response_value(&w_node.result_selector, &result, !is_root, is_root) {
Err(x) => return Err(x),
Ok(x) => x,
};
if w_node.save_as.is_some() {
let var_key = String::from(w_node.save_as.clone().unwrap().trim());
let mut heap = heap.lock().unwrap();
heap.insert(var_key, String::from(&w_node.result));
drop(heap);
}
Ok(())
}
pub async fn send_http_request(node: MuxNode) -> Result<String, Box<dyn Error>> {
let node = node.lock().unwrap();
let client = match node.method.as_str() {
constants::GET => Client::new().get(&node.url),
constants::POST => Client::new().post(&node.url),
constants::PUT => Client::new().put(&node.url),
constants::PATCH => Client::new().patch(&node.url),
constants::DELETE => Client::new().delete(&node.url),
_ => {
return Err(Box::new(RequestError(
constants::ERR_UNKNOWN_METHOD.to_string(),
)))
}
};
let mut request = match &node.body {
None => client,
Some(body_map) => match body_map.body_type {
RequestBodyType::JSON => client.json(&body_map.value),
RequestBodyType::FORM => client.form(&body_map.value),
_ => client.json::<Value>(&serde_json::from_str(&body_map.raw)?),
},
};
if node.headers.is_some() {
request = request.headers(node.headers.clone().unwrap());
}
let response = request.send().await?.text().await?;
Ok(response)
}
fn get_response_value(
path: &String,
response: &String,
just_first_slice_value: bool,
pretty: bool,
) -> Result<String, String> {
if path.len() == 0 {
return Ok(String::from(response));
}
let json_selectable = match JsonPathFinder::from_str(&response[..], &path[..]) {
Err(x) => return Err(x),
Ok(x) => x,
};
if just_first_slice_value {
return match json_selectable.find_slice().to_vec()[0].as_str() {
None => Err(format!("Could not select value to use with this selector: \n{path} \non this response: \n{response}")),
Some(x) => Ok(String::from(x)),
};
}
if pretty {
return match serde_json::to_string_pretty(json_selectable.find_slice().as_slice()) {
Err(x) => Err(x.to_string()),
Ok(x) => Ok(x),
};
}
match serde_json::to_string(json_selectable.find_slice().as_slice()) {
Err(x) => Err(x.to_string()),
Ok(x) => Ok(x),
}
}