Skip to content

Commit 5d82cd8

Browse files
committed
docs, fixes, minor tweaks
1 parent 658c4ee commit 5d82cd8

File tree

6 files changed

+60
-19
lines changed

6 files changed

+60
-19
lines changed

examples/complex_http_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ async fn main() -> Result<()> {
8686
}
8787

8888
let body = if args.body {
89-
Body::from_input_stream(wstd::io::stdin().into_inner()).into_boxed_body()
89+
Body::from_try_stream(wstd::io::stdin().into_inner().into_stream()).into_boxed_body()
9090
} else {
9191
Body::empty().into_boxed_body()
9292
};

examples/http_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ async fn main() -> Result<()> {
7373
// Send the request.
7474

7575
let body = if args.body {
76-
Body::from_input_stream(wstd::io::stdin().into_inner())
76+
Body::from_try_stream(wstd::io::stdin().into_inner().into_stream())
7777
} else {
7878
Body::empty()
7979
};

examples/http_server.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use anyhow::{Context, Result};
22
use futures_lite::stream::once_future;
33
use http_body_util::{BodyExt, StreamBody};
4+
use std::convert::Infallible;
45
use wstd::http::body::{Body, Bytes, Frame};
56
use wstd::http::{Error, HeaderMap, Request, Response, StatusCode};
67
use wstd::time::{Duration, Instant};
@@ -55,7 +56,7 @@ async fn http_wait_body(_request: Request<Body>) -> Result<Response<Body>> {
5556

5657
// Compute how long we slept for.
5758
let elapsed = Instant::now().duration_since(now).as_millis();
58-
Ok(Bytes::from(format!("slept for {elapsed} millis\n")))
59+
Ok::<_, Infallible>(Bytes::from(format!("slept for {elapsed} millis\n")))
5960
};
6061

6162
Ok(Response::new(Body::from_try_stream(once_future(body))))

macro/src/lib.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,18 @@ pub fn attr_macro_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
9393
/// ```ignore
9494
/// #[wstd::http_server]
9595
/// async fn main(request: Request<Body>) -> Result<Response<Body>> {
96-
/// Ok(Response::new("Hello!\n".into_body()))
96+
/// Ok(Response::new("Hello!\n".into()))
9797
/// }
9898
/// ```
9999
#[proc_macro_attribute]
100100
pub fn attr_macro_http_server(_attr: TokenStream, item: TokenStream) -> TokenStream {
101101
let input = parse_macro_input!(item as ItemFn);
102102

103-
if input.sig.asyncness.is_none() {
104-
return quote_spanned! { input.sig.fn_token.span()=>
105-
compile_error!("fn must be `async fn`");
106-
}
107-
.into();
108-
}
103+
let (run_async, run_await) = if input.sig.asyncness.is_some() {
104+
(quote!(async), quote!(.await))
105+
} else {
106+
(quote!(), quote!())
107+
};
109108

110109
let output = &input.sig.output;
111110
let inputs = &input.sig.inputs;
@@ -130,14 +129,14 @@ pub fn attr_macro_http_server(_attr: TokenStream, item: TokenStream) -> TokenStr
130129
response_out: ::wstd::__internal::wasip2::http::types::ResponseOutparam
131130
) {
132131
#(#attrs)*
133-
#vis async fn __run(#inputs) #output {
132+
#vis #run_async fn __run(#inputs) #output {
134133
#body
135134
}
136135

137136
let responder = ::wstd::http::server::Responder::new(response_out);
138137
::wstd::runtime::block_on(async move {
139138
match ::wstd::http::request::try_from_incoming(request) {
140-
Ok(request) => match __run(request).await {
139+
Ok(request) => match __run(request) #run_await {
141140
Ok(response) => { responder.respond(response).await.unwrap() },
142141
Err(err) => responder.fail(err).unwrap(),
143142
}

src/http/body.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,14 @@ pub mod util {
3434
/// from strings.
3535
/// * `Body::from_json` for a `Body` from a `Serialize` (requires feature
3636
/// `json`)
37+
/// * `From<AsyncInputStream>` for a `Body` with contents given by the
38+
/// contents of a WASI input-stream.
3739
/// * `Body::from_stream` or `Body::from_try_stream` for a `Body` from a
3840
/// `Stream` of `Into<Bytes>`
3941
///
40-
/// Consume
42+
/// Consume this HTTP body using:
43+
///
44+
///
4145
#[derive(Debug)]
4246
pub struct Body(BodyInner);
4347

@@ -107,6 +111,10 @@ impl Body {
107111
}
108112
}
109113

114+
/// Convert this `Body` into an `UnsyncBoxBody<Bytes, Error>`, which
115+
/// exists to implement the `http_body::Body` trait. Consume the contents
116+
/// using `http_body_utils::BodyExt`, or anywhere else an impl of
117+
/// `http_body::Body` is accepted.
110118
pub fn into_boxed_body(self) -> UnsyncBoxBody<Bytes, Error> {
111119
fn map_e(_: std::convert::Infallible) -> Error {
112120
unreachable!()
@@ -121,6 +129,9 @@ impl Body {
121129
}
122130
}
123131

132+
/// Collect the entire contents of this `Body`, and expose them as a
133+
/// byte slice. This async fn will be pending until the entire `Body` is
134+
/// copied into memory, or an error occurs.
124135
pub async fn contents(&mut self) -> Result<&[u8], Error> {
125136
match &mut self.0 {
126137
BodyInner::Complete { ref data, .. } => Ok(data.as_ref()),
@@ -149,6 +160,11 @@ impl Body {
149160
}
150161
}
151162

163+
/// Get a value for the length of this `Body`'s content, in bytes, if
164+
/// known. This value can come from either the Content-Length header
165+
/// recieved in the incoming request or response assocated with the body,
166+
/// or be provided by an exact `http_body::Body::size_hint` if the `Body`
167+
/// is constructed from an `http_body::Body` impl.
152168
pub fn content_length(&self) -> Option<u64> {
153169
match &self.0 {
154170
BodyInner::Boxed(b) => b.size_hint().exact(),
@@ -165,16 +181,25 @@ impl Body {
165181
})
166182
}
167183

184+
/// Collect the entire contents of this `Body`, and expose them as a
185+
/// string slice. This async fn will be pending until the entire `Body` is
186+
/// copied into memory, or an error occurs. Additonally errors if the
187+
/// contents of the `Body` were not a utf-8 encoded string.
168188
pub async fn str_contents(&mut self) -> Result<&str, Error> {
169189
let bs = self.contents().await?;
170190
std::str::from_utf8(bs).context("decoding body contents as string")
171191
}
172192

193+
/// Construct a `Body` by serializing a type to json. Can fail with a
194+
/// `serde_json::Error` if serilization fails.
173195
#[cfg(feature = "json")]
174196
pub fn from_json<T: serde::Serialize>(data: &T) -> Result<Self, serde_json::Error> {
175197
Ok(Self::from(serde_json::to_vec(data)?))
176198
}
177199

200+
/// Collect the entire contents of this `Body`, and deserialize them from
201+
/// json. Can fail if the body contents are not utf-8 encoded, are not
202+
/// valid json, or the json is not accepted by the `serde::Deserialize` impl.
178203
#[cfg(feature = "json")]
179204
pub async fn json<T: for<'a> serde::Deserialize<'a>>(&mut self) -> Result<T, Error> {
180205
let str = self.str_contents().await?;
@@ -185,6 +210,8 @@ impl Body {
185210
Body(BodyInner::Incoming(Incoming { body, size_hint }))
186211
}
187212

213+
/// Construct a `Body` backed by a `futures_lite::Stream` impl. The stream
214+
/// will be polled as the body is sent.
188215
pub fn from_stream<S>(stream: S) -> Self
189216
where
190217
S: futures_lite::Stream + Send + 'static,
@@ -196,17 +223,27 @@ impl Body {
196223
))
197224
}
198225

199-
pub fn from_try_stream<S, D>(stream: S) -> Self
226+
/// Construct a `Body` backed by a `futures_lite::Stream` impl. The stream
227+
/// will be polled as the body is sent. If the stream gives an error, the
228+
/// body will canceled, which closes the underlying connection.
229+
pub fn from_try_stream<S, D, E>(stream: S) -> Self
200230
where
201-
S: futures_lite::Stream<Item = Result<D, Error>> + Send + 'static,
231+
S: futures_lite::Stream<Item = Result<D, E>> + Send + 'static,
202232
D: Into<Bytes>,
233+
E: std::error::Error + Send + Sync + 'static,
203234
{
204235
use futures_lite::StreamExt;
205236
Self::from_http_body(http_body_util::StreamBody::new(
206237
stream.map(|bs| Ok::<_, Error>(Frame::data(bs?.into()))),
207238
))
208239
}
209240

241+
/// Construct a `Body` backed by a `http_body::Body`. The http_body will
242+
/// be polled as the body is sent. If the http_body poll gives an error,
243+
/// the body will be canceled, which closes the underlying connection.
244+
///
245+
/// Note, this is the only constructor which permits adding trailers to
246+
/// the `Body`.
210247
pub fn from_http_body<B>(http_body: B) -> Self
211248
where
212249
B: HttpBody + Send + 'static,
@@ -259,9 +296,12 @@ impl From<String> for Body {
259296

260297
impl From<crate::io::AsyncInputStream> for Body {
261298
fn from(r: crate::io::AsyncInputStream) -> Body {
262-
// TODO: with another BodyInner variant for a boxed AsyncRead for which
263-
// as_input_stream is_some, this could allow for use of
264-
// crate::io::copy.
299+
// TODO: this is skipping the wstd::io::copy optimization.
300+
// in future, with another BodyInner variant for a boxed AsyncRead for
301+
// which as_input_stream is_some, this could allow for use of
302+
// crate::io::copy. But, we probably need to redesign AsyncRead to be
303+
// a poll_read func in order to make it possible to use from
304+
// http_body::Body::poll_frame.
265305
use futures_lite::stream::StreamExt;
266306
Body(BodyInner::Boxed(http_body_util::BodyExt::boxed_unsync(
267307
http_body_util::StreamBody::new(r.into_stream().map(|res| {

src/http/server.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//! use wstd::http::{Request, Response, Body, Error};
99
//! #[wstd::http_server]
1010
//! async fn main(_request: Request<Body>) -> Result<Response<Body>, Error> {
11-
//! Ok(Response::new("Hello!\n".to_string().into()))
11+
//! Ok(Response::new("Hello!\n".into()))
1212
//! }
1313
//! ```
1414
//!
@@ -26,6 +26,7 @@ use wasip2::http::types::OutgoingResponse;
2626
/// For use by the [`http_server`] macro only.
2727
///
2828
/// [`http_server`]: crate::http_server
29+
#[doc(hidden)]
2930
#[must_use]
3031
pub struct Responder {
3132
outparam: ResponseOutparam,

0 commit comments

Comments
 (0)