Skip to content

Commit b56706f

Browse files
authored
Implements Response::from_http (#12063)
* Initial attempt at Response::from_http. * Bit of cleanup. * Signal consumption.
1 parent 696ef2c commit b56706f

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

crates/wasi-http/src/p3/response.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,76 @@ impl Response {
8989
};
9090
Ok(http::Response::from_parts(res, body))
9191
}
92+
93+
/// Convert [http::Response] into [Response].
94+
pub fn from_http<T>(
95+
res: http::Response<T>,
96+
) -> (
97+
Self,
98+
impl Future<Output = Result<(), ErrorCode>> + Send + 'static,
99+
)
100+
where
101+
T: http_body::Body<Data = Bytes> + Send + 'static,
102+
T::Error: Into<ErrorCode>,
103+
{
104+
let (parts, body) = res.into_parts();
105+
let (result_tx, result_rx) = tokio::sync::oneshot::channel();
106+
107+
let wasi_response = Response {
108+
status: parts.status,
109+
headers: Arc::new(parts.headers),
110+
body: Body::Host {
111+
body: body.map_err(Into::into).boxed_unsync(),
112+
result_tx,
113+
},
114+
};
115+
116+
let io_future = async {
117+
let Ok(fut) = result_rx.await else {
118+
return Ok(());
119+
};
120+
Box::into_pin(fut).await
121+
};
122+
123+
(wasi_response, io_future)
124+
}
125+
}
126+
127+
#[cfg(test)]
128+
mod tests {
129+
use super::*;
130+
use core::future::Future;
131+
use core::pin::pin;
132+
use core::task::{Context, Poll, Waker};
133+
use http_body_util::Full;
134+
135+
#[tokio::test]
136+
async fn test_response_from_http() {
137+
let http_response = http::Response::builder()
138+
.status(StatusCode::OK)
139+
.header("x-custom-header", "value123")
140+
.body(Full::new(Bytes::from_static(b"hello wasm")))
141+
.unwrap();
142+
143+
let (wasi_resp, io_future) = Response::from_http(http_response);
144+
assert_eq!(wasi_resp.status, StatusCode::OK);
145+
assert_eq!(
146+
wasi_resp.headers.get("x-custom-header").unwrap(),
147+
"value123"
148+
);
149+
match wasi_resp.body {
150+
Body::Host { body, result_tx } => {
151+
let collected = body.collect().await;
152+
assert!(collected.is_ok(), "Body stream failed unexpectedly");
153+
let chunks = collected.unwrap().to_bytes();
154+
assert_eq!(chunks, &b"hello wasm"[..]);
155+
_ = result_tx.send(Box::new(async { Ok(()) }));
156+
}
157+
_ => panic!("Response body should be of type Host"),
158+
}
159+
160+
let mut cx = Context::from_waker(Waker::noop());
161+
let result = pin!(io_future).poll(&mut cx);
162+
assert!(matches!(result, Poll::Ready(Ok(_))));
163+
}
92164
}

0 commit comments

Comments
 (0)