1 use {
2     test_programs::p3::{
3         service::exports::wasi::http::handler::Guest as Handler,
4         wasi::http::{
5             client,
6             types::{ErrorCode, Fields, Request, Response, Scheme},
7         },
8         wit_future,
9     },
10     url::Url,
11 };
12 
13 struct Component;
14 
15 test_programs::p3::service::export!(Component);
16 
17 impl Handler for Component {
18     // Forward the request body and trailers to a URL specified in a header.
handle(request: Request) -> Result<Response, ErrorCode>19     async fn handle(request: Request) -> Result<Response, ErrorCode> {
20         let headers = request.get_headers().copy_all();
21         Ok(
22             if let Some(url) = headers.iter().find_map(|(k, v)| {
23                 (k == "url")
24                     .then_some(v)
25                     .and_then(|v| std::str::from_utf8(v).ok())
26                     .and_then(|v| Url::parse(v).ok())
27             }) {
28                 let method = request.get_method();
29                 let (rx, trailers) = Request::consume_body(request, wit_future::new(|| Ok(())).1);
30                 let outgoing_request = Request::new(Fields::new(), Some(rx), trailers, None).0;
31                 outgoing_request.set_method(&method).unwrap();
32                 outgoing_request
33                     .set_path_with_query(Some(url.path()))
34                     .unwrap();
35                 outgoing_request
36                     .set_scheme(Some(&match url.scheme() {
37                         "http" => Scheme::Http,
38                         "https" => Scheme::Https,
39                         scheme => Scheme::Other(scheme.into()),
40                     }))
41                     .unwrap();
42                 outgoing_request
43                     .set_authority(Some(url.authority()))
44                     .unwrap();
45                 client::send(outgoing_request).await?
46             } else {
47                 bad_request()
48             },
49         )
50     }
51 }
52 
bad_request() -> Response53 fn bad_request() -> Response {
54     respond(400)
55 }
56 
respond(status: u16) -> Response57 fn respond(status: u16) -> Response {
58     let response = Response::new(Fields::new(), None, wit_future::new(|| Ok(None)).1).0;
59     response.set_status_code(status).unwrap();
60     response
61 }
62 
63 // Unused function; required since this file is built as a `bin`:
main()64 fn main() {}
65