use crate::runtime::engine::Runtime;
use crate::runtime::values::Value;
use crate::stdlib::web::{HttpRequest, HttpResponse, Middleware};
use crate::runtime::functions::RuntimeError;
use std::collections::HashMap;
pub fn execute_middleware_chain(
runtime: &mut Runtime,
middleware_list: &[Middleware],
request: HttpRequest,
) -> Result<HttpRequest, MiddlewareError> {
let mut current_request = request;
for middleware in middleware_list {
current_request = execute_middleware(runtime, middleware, current_request)?;
}
Ok(current_request)
}
fn execute_middleware(
runtime: &mut Runtime,
middleware: &Middleware,
request: HttpRequest,
) -> Result<HttpRequest, MiddlewareError> {
let request_value = http_request_to_value(&request);
let args = vec![request_value];
match runtime.call_function(&middleware.handler, &args) {
Ok(result) => {
value_to_http_request(result)
.map_err(|e| MiddlewareError::ExecutionError(format!("Failed to convert response: {}", e)))
}
Err(e) => {
if let RuntimeError::FunctionNotFound(_) = e {
Err(MiddlewareError::HandlerNotFound(middleware.handler.clone()))
} else {
Err(MiddlewareError::ExecutionError(format!("{}", e)))
}
}
}
}
fn http_request_to_value(request: &HttpRequest) -> Value {
let mut map = HashMap::new();
map.insert("method".to_string(), Value::String(request.method.clone()));
map.insert("path".to_string(), Value::String(request.path.clone()));
let mut headers_map = HashMap::new();
for (k, v) in &request.headers {
headers_map.insert(k.clone(), Value::String(v.clone()));
}
map.insert("headers".to_string(), Value::Map(headers_map));
map.insert("body".to_string(), Value::String(request.body.clone()));
let mut query_map = HashMap::new();
for (k, v) in &request.query_params {
query_map.insert(k.clone(), Value::String(v.clone()));
}
map.insert("query_params".to_string(), Value::Map(query_map));
let mut path_map = HashMap::new();
for (k, v) in &request.path_params {
path_map.insert(k.clone(), Value::String(v.clone()));
}
map.insert("path_params".to_string(), Value::Map(path_map));
let mut cookies_map = HashMap::new();
for (k, v) in &request.cookies {
cookies_map.insert(k.clone(), Value::String(v.clone()));
}
map.insert("cookies".to_string(), Value::Map(cookies_map));
map.insert("session".to_string(), Value::Map(request.session.clone()));
if let Some(ref user) = request.user {
let mut user_map = HashMap::new();
user_map.insert("id".to_string(), Value::String(user.id.clone()));
user_map.insert("email".to_string(), Value::String(user.email.clone()));
map.insert("user".to_string(), Value::Map(user_map));
} else {
map.insert("user".to_string(), Value::Null);
}
Value::Map(map)
}
pub fn value_to_http_request(value: Value) -> Result<HttpRequest, String> {
match value {
Value::Map(map) => {
let method = map.get("method")
.and_then(|v| if let Value::String(s) = v { Some(s.clone()) } else { None })
.ok_or_else(|| "Missing method".to_string())?;
let path = map.get("path")
.and_then(|v| if let Value::String(s) = v { Some(s.clone()) } else { None })
.ok_or_else(|| "Missing path".to_string())?;
let headers = map.get("headers")
.and_then(|v| {
if let Value::Map(m) = v {
let mut h = HashMap::new();
for (k, v) in m {
if let Value::String(s) = v {
h.insert(k.clone(), s.clone());
}
}
Some(h)
} else {
None
}
})
.unwrap_or_default();
let body = map.get("body")
.and_then(|v| if let Value::String(s) = v { Some(s.clone()) } else { None })
.unwrap_or_default();
let query_params = map.get("query_params")
.and_then(|v| {
if let Value::Map(m) = v {
let mut q = HashMap::new();
for (k, v) in m {
if let Value::String(s) = v {
q.insert(k.clone(), s.clone());
}
}
Some(q)
} else {
None
}
})
.unwrap_or_default();
let path_params = map.get("path_params")
.and_then(|v| {
if let Value::Map(m) = v {
let mut p = HashMap::new();
for (k, v) in m {
if let Value::String(s) = v {
p.insert(k.clone(), s.clone());
}
}
Some(p)
} else {
None
}
})
.unwrap_or_default();
let cookies = map.get("cookies")
.and_then(|v| {
if let Value::Map(m) = v {
let mut c = HashMap::new();
for (k, v) in m {
if let Value::String(s) = v {
c.insert(k.clone(), s.clone());
}
}
Some(c)
} else {
None
}
})
.unwrap_or_default();
let session = map.get("session")
.and_then(|v| {
if let Value::Map(m) = v {
Some(m.clone())
} else {
None
}
})
.unwrap_or_default();
let user = map.get("user")
.and_then(|v| {
if let Value::Map(m) = v {
let id = m.get("id")
.and_then(|v| if let Value::String(s) = v { Some(s.clone()) } else { None })
.unwrap_or_default();
let username = m.get("username")
.and_then(|v| if let Value::String(s) = v { Some(s.clone()) } else { None })
.unwrap_or_default();
let email = m.get("email")
.and_then(|v| if let Value::String(s) = v { Some(s.clone()) } else { None })
.unwrap_or_default();
let roles = m.get("roles")
.and_then(|v| {
if let Value::List(l) = v {
Some(l.iter().filter_map(|v| {
if let Value::String(s) = v { Some(s.clone()) } else { None }
}).collect())
} else {
None
}
})
.unwrap_or_default();
Some(crate::stdlib::web::User {
id,
username,
email,
roles,
})
} else {
None
}
});
Ok(HttpRequest {
method,
path,
headers,
body,
query_params,
path_params,
cookies,
session,
user,
})
}
_ => Err("Expected Map value".to_string()),
}
}
#[derive(Debug)]
pub enum MiddlewareError {
HandlerNotFound(String),
ExecutionError(String),
ConversionError(String),
}
impl std::fmt::Display for MiddlewareError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
MiddlewareError::HandlerNotFound(name) => write!(f, "Middleware handler not found: {}", name),
MiddlewareError::ExecutionError(msg) => write!(f, "Middleware execution error: {}", msg),
MiddlewareError::ConversionError(msg) => write!(f, "Value conversion error: {}", msg),
}
}
}
impl std::error::Error for MiddlewareError {}
pub fn execute_route_handler(
runtime: &mut Runtime,
handler_name: &str,
request: HttpRequest,
) -> Result<HttpResponse, MiddlewareError> {
let request_value = http_request_to_value(&request);
let args = vec![request_value];
match runtime.call_function(handler_name, &args) {
Ok(result) => {
value_to_http_response(result)
.map_err(|e| MiddlewareError::ExecutionError(format!("Failed to convert response: {}", e)))
}
Err(e) => Err(MiddlewareError::ExecutionError(format!("{}", e))),
}
}
pub fn value_to_http_response(value: Value) -> Result<HttpResponse, String> {
match value {
Value::Map(map) => {
let status = map.get("status")
.and_then(|v| if let Value::Int(i) = v { Some(*i) } else { None })
.unwrap_or(200);
let headers = map.get("headers")
.and_then(|v| {
if let Value::Map(m) = v {
let mut h = HashMap::new();
for (k, v) in m {
if let Value::String(s) = v {
h.insert(k.clone(), s.clone());
}
}
Some(h)
} else {
None
}
})
.unwrap_or_default();
let body = map.get("body")
.and_then(|v| if let Value::String(s) = v { Some(s.clone()) } else { None })
.unwrap_or_default();
let cookies = vec![];
let redirect_url = map.get("redirect_url")
.and_then(|v| if let Value::String(s) = v { Some(s.clone()) } else { None });
Ok(HttpResponse {
status,
headers,
body,
cookies,
redirect_url,
})
}
Value::String(s) => {
Ok(HttpResponse {
status: 200,
headers: HashMap::new(),
body: s,
cookies: vec![],
redirect_url: None,
})
}
_ => Err("Invalid response type".to_string()),
}
}