pub(crate) mod conn;
mod pool;
mod request;
mod ssrf;
mod wire;
use crate::seqstring::{global_bytes, global_string};
use crate::stack::{Stack, pop, push};
use crate::value::{MapKey, Value};
use std::collections::HashMap;
#[cfg(test)]
pub(crate) use ssrf::{is_dangerous_ipv4, is_dangerous_ipv6, validate_url_for_ssrf};
pub(crate) fn build_response_map(
status: i64,
body: Vec<u8>,
ok: bool,
error: Option<String>,
) -> Value {
let mut map: HashMap<MapKey, Value> = HashMap::new();
map.insert(
MapKey::String(global_string("status".to_string())),
Value::Int(status),
);
map.insert(
MapKey::String(global_string("body".to_string())),
Value::String(global_bytes(body)),
);
map.insert(
MapKey::String(global_string("ok".to_string())),
Value::Bool(ok),
);
if let Some(err) = error {
map.insert(
MapKey::String(global_string("error".to_string())),
Value::String(global_string(err)),
);
}
Value::Map(Box::new(map))
}
pub(crate) fn error_response(error: String) -> Value {
build_response_map(0, Vec::new(), false, Some(error))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_http_get(stack: Stack) -> Stack {
assert!(!stack.is_null(), "http.get: stack is empty");
let (stack, url_value) = unsafe { pop(stack) };
match url_value {
Value::String(url) => {
let response = request::perform_request("GET", url.as_str_or_empty(), None);
unsafe { push(stack, response) }
}
_ => panic!("http.get: expected String (URL), got {:?}", url_value),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_http_post(stack: Stack) -> Stack {
assert!(!stack.is_null(), "http.post: stack is empty");
let (stack, content_type_value) = unsafe { pop(stack) };
let (stack, body_value) = unsafe { pop(stack) };
let (stack, url_value) = unsafe { pop(stack) };
match (url_value, body_value, content_type_value) {
(Value::String(url), Value::String(body), Value::String(content_type)) => {
let response = request::perform_request(
"POST",
url.as_str_or_empty(),
Some((content_type.as_str_or_empty(), body.as_bytes())),
);
unsafe { push(stack, response) }
}
(url, body, ct) => panic!(
"http.post: expected (String, String, String), got ({:?}, {:?}, {:?})",
url, body, ct
),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_http_put(stack: Stack) -> Stack {
assert!(!stack.is_null(), "http.put: stack is empty");
let (stack, content_type_value) = unsafe { pop(stack) };
let (stack, body_value) = unsafe { pop(stack) };
let (stack, url_value) = unsafe { pop(stack) };
match (url_value, body_value, content_type_value) {
(Value::String(url), Value::String(body), Value::String(content_type)) => {
let response = request::perform_request(
"PUT",
url.as_str_or_empty(),
Some((content_type.as_str_or_empty(), body.as_bytes())),
);
unsafe { push(stack, response) }
}
(url, body, ct) => panic!(
"http.put: expected (String, String, String), got ({:?}, {:?}, {:?})",
url, body, ct
),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_http_delete(stack: Stack) -> Stack {
assert!(!stack.is_null(), "http.delete: stack is empty");
let (stack, url_value) = unsafe { pop(stack) };
match url_value {
Value::String(url) => {
let response = request::perform_request("DELETE", url.as_str_or_empty(), None);
unsafe { push(stack, response) }
}
_ => panic!("http.delete: expected String (URL), got {:?}", url_value),
}
}
#[cfg(test)]
mod integration_tests;
#[cfg(test)]
mod tests;