use super::{Body, Error, Response, error::ErrorCode, fields::header_map_to_wasi};
use http::header::CONTENT_LENGTH;
use wasip2::exports::http::incoming_handler::ResponseOutparam;
use wasip2::http::types::OutgoingResponse;
#[doc(hidden)]
#[must_use]
pub struct Responder {
outparam: ResponseOutparam,
}
impl Responder {
#[doc(hidden)]
pub async fn respond<B: Into<Body>>(self, response: Response<B>) -> Result<(), Error> {
let headers = response.headers();
let status = response.status().as_u16();
let wasi_headers = header_map_to_wasi(headers).expect("header error");
let body = response.into_body().into();
if let Some(len) = body.content_length() {
let mut buffer = itoa::Buffer::new();
wasi_headers
.append(CONTENT_LENGTH.as_str(), buffer.format(len).as_bytes())
.unwrap();
}
let wasi_response = OutgoingResponse::new(wasi_headers);
wasi_response.set_status_code(status).unwrap();
let wasi_body = wasi_response.body().unwrap();
ResponseOutparam::set(self.outparam, Ok(wasi_response));
body.send(wasi_body).await
}
#[doc(hidden)]
pub fn new(outparam: ResponseOutparam) -> Self {
Self { outparam }
}
#[doc(hidden)]
pub fn fail(self, err: Error) {
let e = match err.downcast_ref::<ErrorCode>() {
Some(e) => e.clone(),
None => ErrorCode::InternalError(Some(format!("{err:?}"))),
};
ResponseOutparam::set(self.outparam, Err(e));
}
}