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 { 48 let (request, mut contents_tx, trailers_tx, transmit) = make_request(); 49 let (transmit, handle) = join!(async { transmit.await }, async { 50 let res = handler::handle(request) 51 .await 52 .context("failed to send request")?; 53 println!("writing enough"); 54 let remaining = contents_tx.write_all(b"long enough".to_vec()).await; 55 assert!( 56 remaining.is_empty(), 57 "{}", 58 String::from_utf8_lossy(&remaining) 59 ); 60 drop(contents_tx); 61 trailers_tx 62 .write(Ok(None)) 63 .await 64 .context("failed to finish body")?; 65 anyhow::Ok(res) 66 }); 67 let res = handle.unwrap(); 68 drop(res); 69 transmit.expect("failed to transmit request"); 70 } 71 72 { 73 let (request, mut contents_tx, trailers_tx, transmit) = make_request(); 74 let (transmit, handle) = join!(async { transmit.await }, async { 75 let res = handler::handle(request) 76 .await 77 .context("failed to send request")?; 78 println!("writing too little"); 79 let remaining = contents_tx.write_all(b"msg".to_vec()).await; 80 assert!( 81 remaining.is_empty(), 82 "{}", 83 String::from_utf8_lossy(&remaining) 84 ); 85 drop(contents_tx); 86 trailers_tx 87 .write(Ok(None)) 88 .await 89 .context("failed to finish body")?; 90 anyhow::Ok(res) 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 { 102 let (request, mut contents_tx, trailers_tx, transmit) = make_request(); 103 let (transmit, handle) = join!(async { transmit.await }, async { 104 let res = handler::handle(request) 105 .await 106 .context("failed to send request")?; 107 println!("writing too much"); 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 anyhow::Ok(res) 117 }); 118 let res = handle.unwrap(); 119 drop(res); 120 let err = transmit.expect_err("request transmission should have failed"); 121 assert!( 122 matches!(err, ErrorCode::HttpRequestBodySize(Some(18))), 123 "unexpected error: {err:#?}" 124 ); 125 } 126 Ok(()) 127 } 128 } 129 130 fn main() {} 131