1 use anyhow::Context as _; 2 use futures::join; 3 use test_programs::p3::wasi::http::handler; 4 use test_programs::p3::wasi::http::types::{ErrorCode, Headers, Method, Request, Scheme, Trailers}; 5 use test_programs::p3::{wit_future, wit_stream}; 6 use wit_bindgen::{FutureReader, FutureWriter, StreamWriter}; 7 8 struct Component; 9 10 test_programs::p3::export!(Component); 11 12 fn make_request() -> ( 13 Request, 14 StreamWriter<u8>, 15 FutureWriter<Result<Option<Trailers>, ErrorCode>>, 16 FutureReader<Result<(), ErrorCode>>, 17 ) { 18 let (contents_tx, contents_rx) = wit_stream::new(); 19 let (trailers_tx, trailers_rx) = wit_future::new(|| todo!()); 20 let (request, transmit) = Request::new( 21 Headers::from_list(&[("Content-Length".to_string(), b"11".to_vec())]).unwrap(), 22 Some(contents_rx), 23 trailers_rx, 24 None, 25 ); 26 27 request.set_method(&Method::Post).expect("setting method"); 28 request 29 .set_scheme(Some(&Scheme::Http)) 30 .expect("setting scheme"); 31 let addr = test_programs::p3::wasi::cli::environment::get_environment() 32 .into_iter() 33 .find_map(|(k, v)| k.eq("HTTP_SERVER").then_some(v)) 34 .unwrap(); 35 request 36 .set_authority(Some(&addr)) 37 .expect("setting authority"); 38 request 39 .set_path_with_query(Some("/")) 40 .expect("setting path with query"); 41 42 (request, contents_tx, trailers_tx, transmit) 43 } 44 45 impl test_programs::p3::exports::wasi::cli::run::Guest for Component { 46 async fn run() -> Result<(), ()> { 47 println!("writing enough"); 48 { 49 let (request, mut contents_tx, trailers_tx, transmit) = make_request(); 50 let (handle, (), ()) = join!( 51 async { 52 let res = handler::handle(request) 53 .await 54 .context("failed to send request")?; 55 anyhow::Ok(res) 56 }, 57 async { 58 let remaining = contents_tx.write_all(b"long enough".to_vec()).await; 59 assert!( 60 remaining.is_empty(), 61 "{}", 62 String::from_utf8_lossy(&remaining) 63 ); 64 trailers_tx.write(Ok(None)).await.unwrap(); 65 drop(contents_tx); 66 }, 67 async { 68 transmit.await.unwrap(); 69 }, 70 ); 71 let res = handle.unwrap(); 72 drop(res); 73 } 74 75 println!("writing too little"); 76 { 77 let (request, mut contents_tx, trailers_tx, transmit) = make_request(); 78 let (handle, transmit, ()) = join!( 79 async { handler::handle(request).await }, 80 async { transmit.await }, 81 async { 82 let remaining = contents_tx.write_all(b"msg".to_vec()).await; 83 assert!( 84 remaining.is_empty(), 85 "{}", 86 String::from_utf8_lossy(&remaining) 87 ); 88 drop(contents_tx); 89 trailers_tx.write(Ok(None)).await.unwrap(); 90 }, 91 ); 92 let res = handle.unwrap(); 93 drop(res); 94 let err = transmit.expect_err("request transmission should have failed"); 95 assert!( 96 matches!(err, ErrorCode::HttpRequestBodySize(Some(3))), 97 "unexpected error: {err:#?}" 98 ); 99 } 100 101 println!("writing too much"); 102 { 103 let (request, mut contents_tx, trailers_tx, transmit) = make_request(); 104 let (handle, transmit, ()) = join!( 105 async { handler::handle(request).await }, 106 async { transmit.await }, 107 async { 108 let remaining = contents_tx.write_all(b"more than 11 bytes".to_vec()).await; 109 assert!( 110 remaining.is_empty(), 111 "{}", 112 String::from_utf8_lossy(&remaining) 113 ); 114 drop(contents_tx); 115 _ = trailers_tx.write(Ok(None)).await; 116 }, 117 ); 118 119 let res = handle.unwrap(); 120 drop(res); 121 let err = transmit.expect_err("request transmission should have failed"); 122 assert!( 123 matches!(err, ErrorCode::HttpRequestBodySize(Some(18))), 124 "unexpected error: {err:#?}" 125 ); 126 } 127 Ok(()) 128 } 129 } 130 131 fn main() {} 132