Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ itertools = "0.14.0"
base64 = "0.22.1"
termcolor = "1.4.1"
flate2 = "1.0.30"
tokio-util = "0.7.4"

# =============================================================================
#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,84 +44,93 @@ fn make_request() -> (

impl test_programs::p3::exports::wasi::cli::run::Guest for Component {
async fn run() -> Result<(), ()> {
println!("writing enough");
{
let (request, mut contents_tx, trailers_tx, transmit) = make_request();
let (transmit, handle) = join!(async { transmit.await }, async {
let res = handler::handle(request)
.await
.context("failed to send request")?;
println!("writing enough");
let remaining = contents_tx.write_all(b"long enough".to_vec()).await;
assert!(
remaining.is_empty(),
"{}",
String::from_utf8_lossy(&remaining)
);
drop(contents_tx);
trailers_tx
.write(Ok(None))
.await
.context("failed to finish body")?;
anyhow::Ok(res)
});
let (handle, (), ()) = join!(
async {
let res = handler::handle(request)
.await
.context("failed to send request")?;
anyhow::Ok(res)
},
async {
let remaining = contents_tx.write_all(b"long enough".to_vec()).await;
assert!(
remaining.is_empty(),
"{}",
String::from_utf8_lossy(&remaining)
);
trailers_tx.write(Ok(None)).await.unwrap();
drop(contents_tx);
},
async {
transmit.await.unwrap();
},
);
let res = handle.unwrap();
drop(res);
transmit.expect("failed to transmit request");
}

println!("writing too little");
{
let (request, mut contents_tx, trailers_tx, transmit) = make_request();
let (transmit, handle) = join!(async { transmit.await }, async {
let res = handler::handle(request)
.await
.context("failed to send request")?;
println!("writing too little");
let remaining = contents_tx.write_all(b"msg".to_vec()).await;
assert!(
remaining.is_empty(),
"{}",
String::from_utf8_lossy(&remaining)
);
drop(contents_tx);
trailers_tx
.write(Ok(None))
.await
.context("failed to finish body")?;
anyhow::Ok(res)
});
let res = handle.unwrap();
drop(res);
let err = transmit.expect_err("request transmission should have failed");
assert!(
matches!(err, ErrorCode::HttpRequestBodySize(Some(3))),
"unexpected error: {err:#?}"
let (handle, (), ()) = join!(
async { handler::handle(request).await },
async {
transmit.await.unwrap();
},
async {
let remaining = contents_tx.write_all(b"msg".to_vec()).await;
assert!(
remaining.is_empty(),
"{}",
String::from_utf8_lossy(&remaining)
);
drop(contents_tx);
trailers_tx.write(Ok(None)).await.unwrap();
},
);
// FIXME(#11631) should have a more precise error like the one
Comment thread
rvolosatovs marked this conversation as resolved.
Outdated
// commented out.
assert!(matches!(handle.unwrap_err(), ErrorCode::HttpProtocolError));
// let err = transmit.expect_err("request transmission should have failed");
// assert!(
// matches!(err, ErrorCode::HttpRequestBodySize(Some(3))),
// "unexpected error: {err:#?}"
// );
}

println!("writing too much");
{
let (request, mut contents_tx, trailers_tx, transmit) = make_request();
let (transmit, handle) = join!(async { transmit.await }, async {
let res = handler::handle(request)
.await
.context("failed to send request")?;
println!("writing too much");
let remaining = contents_tx.write_all(b"more than 11 bytes".to_vec()).await;
assert!(
remaining.is_empty(),
"{}",
String::from_utf8_lossy(&remaining)
);
drop(contents_tx);
_ = trailers_tx.write(Ok(None)).await;
anyhow::Ok(res)
});
let res = handle.unwrap();
drop(res);
let err = transmit.expect_err("request transmission should have failed");
assert!(
matches!(err, ErrorCode::HttpRequestBodySize(Some(18))),
"unexpected error: {err:#?}"
let (handle, (), ()) = join!(
async { handler::handle(request).await },
async {
transmit.await.unwrap();
},
async {
let remaining = contents_tx.write_all(b"more than 11 bytes".to_vec()).await;
assert!(
remaining.is_empty(),
"{}",
String::from_utf8_lossy(&remaining)
);
drop(contents_tx);
_ = trailers_tx.write(Ok(None)).await;
},
);

// FIXME(#11631) something here should fail, but all these unwraps
// pass... Previous error code is below.
handle.unwrap();
// let res = handle.unwrap();
// drop(res);
// let err = transmit.expect_err("request transmission should have failed");
// assert!(
// matches!(err, ErrorCode::HttpRequestBodySize(Some(18))),
// "unexpected error: {err:#?}"
// );
}
Ok(())
}
Expand Down
3 changes: 2 additions & 1 deletion crates/wasi-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ workspace = true
[features]
default = ["default-send-request"]
default-send-request = ["dep:tokio-rustls", "dep:rustls", "dep:webpki-roots"]
p3 = ["wasmtime-wasi/p3"]
p3 = ["wasmtime-wasi/p3", "dep:tokio-util"]

[dependencies]
anyhow = { workspace = true }
Expand All @@ -27,6 +27,7 @@ tokio = { workspace = true, features = [
"rt-multi-thread",
"time",
] }
tokio-util = { workspace = true, optional = true }
http = { workspace = true }
http-body = { workspace = true }
http-body-util = { workspace = true }
Expand Down
19 changes: 19 additions & 0 deletions crates/wasi-http/src/p3/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,31 @@ mod generated {
world: "wasi:http/proxy",
imports: {
"wasi:http/handler/[async]handle": async | store | trappable | tracing,
"wasi:http/types/[method]request.consume-body": async | store | trappable | tracing,
"wasi:http/types/[method]response.consume-body": async | store | trappable | tracing,
"wasi:http/types/[static]request.new": async | store | trappable | tracing,
"wasi:http/types/[static]response.new": async | store | trappable | tracing,
default: trappable | tracing,
},
exports: { default: async | store },
with: {
"wasi:http/types/fields": with::Fields,
"wasi:http/types/request": crate::p3::Request,
"wasi:http/types/request-options": with::RequestOptions,
"wasi:http/types/response": crate::p3::Response,
},
trappable_error_type: {
"wasi:http/types/error-code" => crate::p3::HttpError,
},
});

mod with {
/// The concrete type behind a `wasi:http/types/fields` resource.
pub type Fields = crate::p3::MaybeMutable<http::HeaderMap>;

/// The concrete type behind a `wasi:http/types/request-options` resource.
pub type RequestOptions = crate::p3::MaybeMutable<crate::p3::RequestOptions>;
}
}

pub use self::generated::wasi::*;
Expand Down
Loading