use crate::{
common::config::env_loader,
engine::interfaces::{ExternalApiResponse, MiddlewareOutput, ResolvedInputs},
};
use anyhow::{Result, anyhow};
use fancy_log::{LogLevel, log};
use std::time::Duration;
pub async fn execute(url: &str, name: &str, inputs: ResolvedInputs) -> Result<MiddlewareOutput> {
log(
LogLevel::Debug,
&format!("➜ Executing external HTTP middleware: {name}"),
);
let skip_tls = env_loader::to_lowercase(&env_loader::get_env(
"EXTERNAL_HTTPS_CALL_SKIP_TLS_VERIFY",
"false".to_owned(),
)) == "true";
if skip_tls {
log(
LogLevel::Debug,
&format!(
"⚠ TLS Verification disabled for external plugin '{name}' via EXTERNAL_HTTPS_CALL_SKIP_TLS_VERIFY."
),
);
}
let timeout_secs = env_loader::get_env("FLOW_EXECUTION_TIMEOUT_SECS", "10".to_owned())
.parse::<u64>()
.unwrap_or(10);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(timeout_secs)) .danger_accept_invalid_certs(skip_tls)
.build()
.map_err(|e| anyhow!("Failed to build HTTP client: {e}"))?;
let response = match client.post(url).json(&inputs).send().await {
Ok(r) => r,
Err(e) => {
log(
LogLevel::Error,
&format!("✗ External HTTP request failed for '{name}': {e}"),
);
return Ok(MiddlewareOutput {
branch: "failure".into(),
store: None,
});
}
};
if !response.status().is_success() {
log(
LogLevel::Error,
&format!(
"✗ External plugin '{}' returned HTTP error: {}",
name,
response.status()
),
);
return Ok(MiddlewareOutput {
branch: "failure".into(),
store: None,
});
}
let api_response: ExternalApiResponse<MiddlewareOutput> = match response.json().await {
Ok(r) => r,
Err(e) => {
log(
LogLevel::Error,
&format!("✗ Failed to parse external API response JSON for '{name}': {e}"),
);
return Ok(MiddlewareOutput {
branch: "failure".into(),
store: None,
});
}
};
if api_response.status == "success" {
api_response
.data
.ok_or_else(|| anyhow!("External API for '{name}' returned success but 'data' is missing."))
} else {
let msg = api_response
.message
.unwrap_or_else(|| "Unknown error".to_owned());
log(
LogLevel::Warn,
&format!("⚠ External API for '{name}' returned error status: {msg}"),
);
Ok(MiddlewareOutput {
branch: "failure".into(),
store: None,
})
}
}