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.
handle(request: Request) -> Result<Response, ErrorCode>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`:
main()63 fn main() {}
64