use crate::{
bindings::wasi::http::types::{
IncomingResponse, OutgoingBody, OutgoingResponse, ResponseOutparam,
},
body::{write_to_outgoing_body, Body},
header::HeaderMap,
ErrorCode,
};
use anyhow::{Error, Result};
pub struct ResponseBuilder {
pub(crate) inner: Result<Response>,
}
impl Default for ResponseBuilder {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl ResponseBuilder {
#[inline]
pub fn new() -> Self {
Self {
inner: Ok(Response::new()),
}
}
#[inline]
pub fn status_code(mut self, status_code: u16) -> Self {
if let Ok(ref mut resp) = self.inner {
resp.status_code = status_code;
}
self
}
#[inline]
pub fn build(self) -> Result<Response, ErrorCode> {
match self.inner {
Ok(inner) => Ok(inner),
Err(e) => Err(ErrorCode::InternalError(Some(e.to_string()))),
}
}
}
pub struct Response {
pub(crate) headers: HeaderMap,
pub(crate) body: Body,
status_code: u16,
}
impl Default for Response {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl TryFrom<IncomingResponse> for Response {
type Error = Error;
fn try_from(incoming_response: IncomingResponse) -> std::result::Result<Self, Self::Error> {
let status_code = incoming_response.status();
let headers = incoming_response.headers_map()?;
let incoming_body = incoming_response.consume().unwrap();
drop(incoming_response);
Ok(Self {
headers,
status_code,
body: Body::Stream(incoming_body.into()),
})
}
}
impl Response {
#[inline]
pub fn new() -> Self {
Self {
headers: HeaderMap::new(),
status_code: 200,
body: Body::Bytes(vec![]),
}
}
#[inline]
pub fn builder() -> ResponseBuilder {
ResponseBuilder::new()
}
#[inline]
pub fn status_code(&self) -> u16 {
self.status_code
}
}
pub fn handle_response(response_out: ResponseOutparam, response: Response) {
let outgoing_response = OutgoingResponse::new(response.headers.try_into().unwrap());
outgoing_response
.set_status_code(response.status_code)
.unwrap();
let outgoing_body = outgoing_response.body().unwrap();
ResponseOutparam::set(response_out, Ok(outgoing_response));
let body = response.body.bytes().unwrap();
write_to_outgoing_body(&outgoing_body, body.as_slice()).unwrap();
OutgoingBody::finish(outgoing_body, None).unwrap();
}