use boa_engine::{Context, Source};
use indexmap::IndexMap;
use tracing::{info, trace};
use crate::app::app::App;
use crate::models::request::Request;
use crate::models::response::RequestResponse;
use crate::models::scripts::ScriptType;
impl App<'_> {
pub fn modify_request_script(&mut self, collection_index: usize, request_index: usize, script_type: &ScriptType, script: Option<String>) -> anyhow::Result<()> {
let local_selected_request = self.get_request_as_local_from_indexes(&(collection_index, request_index));
{
let mut selected_request = local_selected_request.write();
match script_type {
ScriptType::Pre => selected_request.scripts.pre_request_script = script,
ScriptType::Post => selected_request.scripts.post_request_script = script,
}
info!("{}-request script set", script_type);
}
self.save_collection_to_file(collection_index);
Ok(())
}
}
const JS_CONSOLE: &str = r#"
let console_log_output = "";
globalThis.console = {
log: (msg) => {
console_log_output += msg + '\n';
return msg;
}
}
"#;
const JS_UTILS: &str = r#"
function pretty_print(data) {
console.log(JSON.stringify(data, null, 2));
}
"#;
pub fn execute_pre_request_script(user_script: &String, request: &Request, env: Option<IndexMap<String, String>>) -> (Option<Request>, Option<IndexMap<String, String>>, String) {
let mut context = Context::default();
let request_json = serde_json::to_string(request).unwrap();
let env_json = match &env {
Some(env) => serde_json::to_string(env).unwrap(),
None => String::from("undefined")
};
let script = format!(r#"
let request = {request_json};
let env = {env_json};
{JS_CONSOLE}
{JS_UTILS}
/* Start of the user script */
{user_script}
/* End of the user script */
JSON.stringify([request, env, console_log_output])
"#);
trace!("Executing pre-request script");
let result = match context.eval(Source::from_bytes(&script)) {
Ok(result) => result,
Err(error) => {
return (None, env, error.to_string())
}
};
let stringed_result = result.as_string().unwrap().to_std_string_escaped();
let (result_request, result_env_values, console_output) = match serde_json::from_str::<(Request, Option<IndexMap<String, String>>, String)>(&stringed_result) {
Ok((result_request, result_env_values, console_output)) => (Some(result_request), result_env_values, console_output),
Err(error) => (None, env, error.to_string())
};
return (result_request, result_env_values, console_output);
}
pub fn execute_post_request_script(user_script: &String, response: &RequestResponse, env: Option<IndexMap<String, String>>) -> (Option<RequestResponse>, Option<IndexMap<String, String>>, String) {
let mut context = Context::default();
let response_json = serde_json::to_string(response).unwrap();
let env_json = match &env {
Some(env) => serde_json::to_string(env).unwrap(),
None => String::from("undefined")
};
let script = format!(r#"
let response = {response_json};
let env = {env_json};
{JS_CONSOLE}
{JS_UTILS}
/* Start of the user script */
{user_script}
/* End of the user script */
JSON.stringify([response, env, console_log_output])
"#);
trace!("Executing post-request script");
let result = match context.eval(Source::from_bytes(&script)) {
Ok(result) => result,
Err(error) => {
return (None, env, error.to_string())
}
};
let stringed_result = result.as_string().unwrap().to_std_string_escaped();
let (response_result, result_env_values, console_output) = match serde_json::from_str::<(RequestResponse, Option<IndexMap<String, String>>, String)>(&stringed_result) {
Ok((mut response_result, result_env_values, console_output)) => {
response_result.duration = response.duration.clone();
response_result.status_code = response.status_code.clone();
(Some(response_result), result_env_values, console_output)
},
Err(error) => (None, env, error.to_string())
};
return (response_result, result_env_values, console_output);
}