use std::io::{BufReader, Write};
use http::{HeaderMap, Method, Uri};
use crate::{Body, BodyInner, WcgiError};
#[derive(serde::Serialize, serde::Deserialize)]
struct SerdeRequest {
#[serde(with = "http_serde::method")]
method: Method,
#[serde(with = "http_serde::uri")]
uri: Uri,
#[serde(with = "http_serde::header_map")]
headers: HeaderMap,
body: Option<Vec<u8>>,
}
pub const ENV_VAR_REQUEST_JSON_V1: &str = "__WCGI_REQUEST_JSON_V1";
pub fn extract_request() -> Result<crate::Request, WcgiError> {
let header = std::env::var(ENV_VAR_REQUEST_JSON_V1).map_err(|_| {
let env = std::env::vars().collect::<Vec<_>>();
WcgiError::msg(format!(
"Could not read {ENV_VAR_REQUEST_JSON_V1} env var \n\n({env:?})"
))
})?;
let sr: SerdeRequest = serde_json::from_slice(header.as_bytes())
.map_err(|err| WcgiError::wrap(err, "could not deserialize request header"))?;
let body = if let Some(data) = sr.body {
Body::from(data)
} else {
let lock = std::io::stdin().lock();
Body(BodyInner::Stream(BufReader::new(Box::new(lock))))
};
let mut request = http::Request::new(body);
*request.method_mut() = sr.method;
*request.uri_mut() = sr.uri;
*request.headers_mut() = sr.headers;
Ok(request)
}
pub fn serialize_request_header_v1_json(
request: http::Request<Option<Vec<u8>>>,
) -> Result<String, serde_json::Error> {
let (parts, body) = request.into_parts();
let request2 = SerdeRequest {
method: parts.method,
uri: parts.uri,
headers: parts.headers,
body,
};
serde_json::to_string(&request2)
}
#[derive(serde::Serialize, serde::Deserialize)]
struct SerdeResponse {
#[serde(with = "http_serde::status_code")]
status: http::StatusCode,
#[serde(with = "http_serde::header_map")]
headers: HeaderMap,
}
pub fn deserialize_response_header_v1_json(
data: &[u8],
) -> Result<http::Response<Option<Vec<u8>>>, WcgiError> {
let res: SerdeResponse = serde_json::from_slice(data)
.map_err(|err| WcgiError::wrap(err, "Could not deserialize response"))?;
let mut res2 = http::Response::new(None);
*res2.status_mut() = res.status;
*res2.headers_mut() = res.headers;
Ok(res2)
}
pub fn send_response_and_terminate(res: crate::Response) {
let (parts, body) = res.into_parts();
let res = SerdeResponse {
status: parts.status,
headers: parts.headers,
};
let mut json_header = serde_json::to_vec(&res).unwrap();
json_header.push(b'\n');
let mut stdout = std::io::stdout().lock();
stdout
.write_all(&json_header)
.expect("could not write response header");
match body.0 {
BodyInner::Empty => {}
BodyInner::Data(data) => {
stdout
.write_all(&data.into_inner())
.expect("could not write response body");
}
BodyInner::Stream(mut stream) => {
std::io::copy(&mut stream, &mut stdout).expect("could not write response body");
}
}
}