1 use { 2 test_programs::p3::{ 3 service::exports::wasi::http::handler::Guest as Handler, 4 wasi::http::types::{ErrorCode, Request, Response}, 5 wit_future, wit_stream, 6 }, 7 wit_bindgen::StreamResult, 8 }; 9 10 struct Component; 11 12 test_programs::p3::service::export!(Component); 13 14 impl Handler for Component { 15 /// Return a response which echoes the request headers, body, and trailers. 16 async fn handle(request: Request) -> Result<Response, ErrorCode> { 17 let headers = request.get_headers(); 18 let (_, result_rx) = wit_future::new(|| Ok(())); 19 let (body, trailers) = Request::consume_body(request, result_rx); 20 21 let (response, _result) = if headers 22 .get("x-host-to-host") 23 .into_iter() 24 .any(|v| v == b"true") 25 { 26 // This is the easy and efficient way to do it... 27 Response::new(headers, Some(body), trailers) 28 } else { 29 // ...but we do it the more difficult, less efficient way here to exercise various component model 30 // features (e.g. `future`s, `stream`s, and post-return asynchronous execution): 31 let (trailers_tx, trailers_rx) = wit_future::new(|| todo!()); 32 let (mut pipe_tx, pipe_rx) = wit_stream::new(); 33 34 wit_bindgen::spawn(async move { 35 let mut body_rx = body; 36 let mut chunk = Vec::with_capacity(1024); 37 loop { 38 let (status, buf) = body_rx.read(chunk).await; 39 chunk = buf; 40 match status { 41 StreamResult::Complete(_) => { 42 chunk = pipe_tx.write_all(chunk).await; 43 assert!(chunk.is_empty()); 44 } 45 StreamResult::Dropped => break, 46 StreamResult::Cancelled => unreachable!(), 47 } 48 } 49 50 drop(pipe_tx); 51 52 trailers_tx.write(trailers.await).await.unwrap(); 53 }); 54 55 Response::new(headers, Some(pipe_rx), trailers_rx) 56 }; 57 58 Ok(response) 59 } 60 } 61 62 // Unused function; required since this file is built as a `bin`: 63 fn main() {} 64