@@ -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