Skip to content

Commit

Permalink
fix: make big bodies to send correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
pimeys authored and brooksmtownsend committed Aug 15, 2024
1 parent 2619da3 commit 29adeeb
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 25 deletions.
14 changes: 13 additions & 1 deletion src/wasm/component/client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![allow(warnings)]

use http::header::USER_AGENT;
use http::header::{CONTENT_LENGTH, USER_AGENT};
use http::{HeaderMap, HeaderValue, Method};
use std::any::Any;
use std::convert::TryInto;
Expand Down Expand Up @@ -175,17 +175,29 @@ fn fetch(req: Request) -> crate::Result<ResponseFuture> {
.map_err(crate::error::builder)?;
}

if let Some(body) = req.body().and_then(|b| b.as_bytes()) {
headers
.append(
&CONTENT_LENGTH.to_string(),
&format!("{}", body.len()).as_bytes().to_vec(),
)
.map_err(crate::error::builder)?;
}

// Construct `OutgoingRequest`
let outgoing_request = wasi::http::types::OutgoingRequest::new(headers);
let url = req.url();

if url.has_authority() {
outgoing_request
.set_authority(Some(url.authority()))
.map_err(|_| crate::error::request("failed to set authority on request"))?;
}

outgoing_request
.set_path_with_query(Some(url.path()))
.map_err(|_| crate::error::request("failed to set path with query on request"))?;

match url.scheme() {
"http" => outgoing_request.set_scheme(Some(&wasi::http::types::Scheme::Http)),
"https" => outgoing_request.set_scheme(Some(&wasi::http::types::Scheme::Https)),
Expand Down
47 changes: 24 additions & 23 deletions src/wasm/component/client/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,16 @@ impl ResponseFuture {
return Err(crate::error::request("outgoing body write error"));
};

RequestState::Write(RequestWriteState {
outgoing_request: Some(outgoing_request),
outgoing_body: Some(outgoing_body),
stream: Some(stream),
body,
bytes_written: 0,
})
match wasi::http::outgoing_handler::handle(outgoing_request, None) {
Ok(future) => RequestState::Write(RequestWriteState {
response_future: Some(future),
outgoing_body: Some(outgoing_body),
stream: Some(stream),
body,
bytes_written: 0,
}),
Err(e) => return Err(crate::error::request("request error")),
}
}
None => match wasi::http::outgoing_handler::handle(outgoing_request, None) {
Ok(future) => RequestState::Response(future),
Expand Down Expand Up @@ -101,7 +104,7 @@ enum RequestState {

#[derive(Debug)]
struct RequestWriteState {
outgoing_request: Option<OutgoingRequest>,
response_future: Option<FutureIncomingResponse>,
outgoing_body: Option<OutgoingBody>,
stream: Option<OutputStream>,
body: Body,
Expand All @@ -126,31 +129,35 @@ impl Future for RequestWriteState {
// stream is ready when all data is flushed, and if we wrote all the bytes we
// are ready to continue.
if this.bytes_written == bytes.len() as u64 {
if stream.flush().is_err() {
return Poll::Ready(Err(crate::error::request(
"outgoing body write flush error",
)));
}

if stream.subscribe().ready() {
// will trap if not dropped before body
drop(stream);

let outgoing_request = this.outgoing_request.take().expect("state error");
let future = this.response_future.take().expect("state error");
let outgoing_body = this.outgoing_body.take().expect("state error");

if OutgoingBody::finish(outgoing_body, None).is_err() {
return Poll::Ready(Err(crate::error::request("request error")));
}

match wasi::http::outgoing_handler::handle(outgoing_request, None) {
Ok(future) => {
return Poll::Ready(Ok(future));
}
Err(e) => {
return Poll::Ready(Err(crate::error::request("request error")));
}
}
return Poll::Ready(Ok(future));
} else {
this.stream.insert(stream);
cx.waker().wake_by_ref();

return Poll::Pending;
}
} else if !stream.subscribe().ready() {
this.stream.insert(stream);
cx.waker().wake_by_ref();

return Poll::Pending;
}

let Ok(bytes_to_write) = stream
Expand All @@ -171,12 +178,6 @@ impl Future for RequestWriteState {
)));
};

if stream.flush().is_err() {
return Poll::Ready(Err(crate::error::request(
"outgoing body write flush error",
)));
}

this.bytes_written += bytes_to_write;
this.stream.insert(stream);

Expand Down
2 changes: 1 addition & 1 deletion src/wasm/component/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use url::Url;
use web_sys::RequestCredentials;

use super::{Body, Client, Response};
use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_LENGTH, CONTENT_TYPE};

/// A request which can be executed with `Client::execute()`.
pub struct Request {
Expand Down

0 comments on commit 29adeeb

Please sign in to comment.