pub use http::Request;
pub use http::Response;
#[doc(hidden)]
pub fn request_raw<R>(request: &[u8], run_fn: R)
where
R: FnOnce(&[u8]) -> Vec<u8>,
{
crate::init();
let response = run_fn(request);
ark_api::core::return_slice(&response);
}
#[doc(hidden)]
pub fn request<R>(raw_request: &[u8], run_fn: R)
where
R: FnOnce(Request<Vec<u8>>) -> Response<Vec<u8>>,
{
crate::init();
let request = read_http_request(raw_request);
let response = run_fn(request);
let raw_response = write_http_response(response);
ark_api::core::return_slice(&raw_response);
}
#[doc(hidden)]
pub fn write_http_response(res: Response<Vec<u8>>) -> Vec<u8> {
use std::io::Write;
assert!(res.version() == http::Version::HTTP_11);
assert!(res.extensions().is_empty()); let mut output = Vec::new();
writeln!(
&mut output,
"HTTP/1.1 {status_code} {status_text}",
status_code = res.status().as_u16(),
status_text = res.status().canonical_reason().unwrap_or_default()
)
.unwrap();
for (header, value) in res.headers() {
writeln!(
&mut output,
"{header}: {value}",
header = header.as_str(),
value = value.to_str().unwrap()
)
.unwrap();
}
writeln!(&mut output).unwrap();
output.write_all(res.body()).unwrap();
output
}
#[doc(hidden)]
pub fn read_http_request(raw_request: &[u8]) -> http::Request<Vec<u8>> {
let mut headers = [httparse::EMPTY_HEADER; 64];
let mut parsed_request = httparse::Request::new(&mut headers);
let body_offset = match parsed_request.parse(raw_request).unwrap() {
httparse::Status::Complete(offset) => offset,
httparse::Status::Partial => panic!("partial http response"), };
let mut builder = http::Request::builder()
.method(http::Method::from_bytes(parsed_request.method.unwrap().as_bytes()).unwrap())
.uri(parsed_request.path.unwrap_or_default());
for header in parsed_request.headers {
builder = builder.header(header.name, header.value);
}
let request = builder
.body(raw_request.split_at(body_offset).1.to_vec())
.unwrap();
request
}
#[macro_export(local_inner_macros)]
macro_rules! impl_servlet {
($request_fn:ident) => {
#[no_mangle]
unsafe fn ark_servlet_request(request_ptr: *const u8, request_len: u32) -> u32 {
let arg_str = unsafe { $crate::util::param_byte_slice(request_ptr, request_len) };
ark_module::servlet::request(arg_str, $request_fn);
0
}
};
}
#[macro_export(local_inner_macros)]
macro_rules! impl_servlet_raw {
($request_fn:ident) => {
#[no_mangle]
unsafe fn ark_servlet_request(request_ptr: *const u8, request_len: u32) -> u32 {
let arg_str = unsafe { $crate::util::param_byte_slice(request_ptr, request_len) };
ark_module::servlet::request_raw(arg_str, $request_fn);
0
}
};
}