1- use wstd:: http:: body:: { BodyForthcoming , IncomingBody , OutgoingBody } ;
2- use wstd:: http:: server:: { Finished , Responder } ;
3- use wstd:: http:: { IntoBody , Request , Response , StatusCode } ;
4- use wstd:: io:: { copy, empty, AsyncWrite } ;
1+ use anyhow:: { Context , Result } ;
2+ use futures_lite:: stream:: { once_future, unfold} ;
3+ use http_body_util:: { BodyExt , StreamBody } ;
4+ use std:: convert:: Infallible ;
5+ use wstd:: http:: body:: { Body , Bytes , Frame } ;
6+ use wstd:: http:: { Error , HeaderMap , Request , Response , StatusCode } ;
57use wstd:: time:: { Duration , Instant } ;
68
79#[ wstd:: http_server]
8- async fn main ( request : Request < IncomingBody > , responder : Responder ) -> Finished {
9- match request. uri ( ) . path_and_query ( ) . unwrap ( ) . as_str ( ) {
10- "/wait" => http_wait ( request, responder) . await ,
11- "/echo" => http_echo ( request, responder) . await ,
12- "/echo-headers" => http_echo_headers ( request, responder) . await ,
13- "/echo-trailers" => http_echo_trailers ( request, responder) . await ,
14- "/fail" => http_fail ( request, responder) . await ,
15- "/bigfail" => http_bigfail ( request, responder) . await ,
16- "/" => http_home ( request, responder) . await ,
17- _ => http_not_found ( request, responder) . await ,
10+ async fn main ( request : Request < Body > ) -> Result < Response < Body > , Error > {
11+ let path = request. uri ( ) . path_and_query ( ) . unwrap ( ) . as_str ( ) ;
12+ println ! ( "serving {path}" ) ;
13+ match path {
14+ "/" => http_home ( request) . await ,
15+ "/wait-response" => http_wait_response ( request) . await ,
16+ "/wait-body" => http_wait_body ( request) . await ,
17+ "/stream-body" => http_stream_body ( request) . await ,
18+ "/echo" => http_echo ( request) . await ,
19+ "/echo-headers" => http_echo_headers ( request) . await ,
20+ "/echo-trailers" => http_echo_trailers ( request) . await ,
21+ "/response-status" => http_response_status ( request) . await ,
22+ "/response-fail" => http_response_fail ( request) . await ,
23+ "/response-body-fail" => http_body_fail ( request) . await ,
24+ _ => http_not_found ( request) . await ,
1825 }
1926}
2027
21- async fn http_home ( _request : Request < IncomingBody > , responder : Responder ) -> Finished {
28+ async fn http_home ( _request : Request < Body > ) -> Result < Response < Body > > {
2229 // To send a single string as the response body, use `Responder::respond`.
23- responder
24- . respond ( Response :: new ( "Hello, wasi:http/proxy world!\n " . into_body ( ) ) )
25- . await
30+ Ok ( Response :: new (
31+ "Hello, wasi:http/proxy world!\n " . to_owned ( ) . into ( ) ,
32+ ) )
2633}
2734
28- async fn http_wait ( _request : Request < IncomingBody > , responder : Responder ) -> Finished {
35+ async fn http_wait_response ( _request : Request < Body > ) -> Result < Response < Body > > {
2936 // Get the time now
3037 let now = Instant :: now ( ) ;
3138
@@ -35,60 +42,107 @@ async fn http_wait(_request: Request<IncomingBody>, responder: Responder) -> Fin
3542 // Compute how long we slept for.
3643 let elapsed = Instant :: now ( ) . duration_since ( now) . as_millis ( ) ;
3744
38- // To stream data to the response body, use `Responder::start_response`.
39- let mut body = responder. start_response ( Response :: new ( BodyForthcoming ) ) ;
40- let result = body
41- . write_all ( format ! ( "slept for {elapsed} millis\n " ) . as_bytes ( ) )
42- . await ;
43- Finished :: finish ( body, result, None )
45+ Ok ( Response :: new (
46+ format ! ( "slept for {elapsed} millis\n " ) . into ( ) ,
47+ ) )
4448}
4549
46- async fn http_echo ( mut request : Request < IncomingBody > , responder : Responder ) -> Finished {
47- // Stream data from the request body to the response body.
48- let mut body = responder. start_response ( Response :: new ( BodyForthcoming ) ) ;
49- let result = copy ( request. body_mut ( ) , & mut body) . await ;
50- Finished :: finish ( body, result, None )
51- }
50+ async fn http_wait_body ( _request : Request < Body > ) -> Result < Response < Body > > {
51+ // Get the time now
52+ let now = Instant :: now ( ) ;
53+
54+ let body = async move {
55+ // Sleep for one second.
56+ wstd:: task:: sleep ( Duration :: from_secs ( 1 ) ) . await ;
57+
58+ // Compute how long we slept for.
59+ let elapsed = Instant :: now ( ) . duration_since ( now) . as_millis ( ) ;
60+ Ok :: < _ , Infallible > ( Bytes :: from ( format ! ( "slept for {elapsed} millis\n " ) ) )
61+ } ;
5262
53- async fn http_fail ( _request : Request < IncomingBody > , responder : Responder ) -> Finished {
54- let body = responder. start_response ( Response :: new ( BodyForthcoming ) ) ;
55- Finished :: fail ( body)
63+ Ok ( Response :: new ( Body :: from_try_stream ( once_future ( body) ) ) )
5664}
5765
58- async fn http_bigfail ( _request : Request < IncomingBody > , responder : Responder ) -> Finished {
59- async fn write_body ( body : & mut OutgoingBody ) -> wstd:: io:: Result < ( ) > {
60- for _ in 0 ..0x10 {
61- body. write_all ( "big big big big\n " . as_bytes ( ) ) . await ?;
66+ async fn http_stream_body ( _request : Request < Body > ) -> Result < Response < Body > > {
67+ // Get the time now
68+ let start = Instant :: now ( ) ;
69+
70+ let body = move |iters : usize | async move {
71+ if iters == 0 {
72+ return None ;
6273 }
63- body. flush ( ) . await ?;
64- Ok ( ( ) )
65- }
74+ // Sleep for 0.1 second.
75+ wstd:: task:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
76+
77+ // Compute how long we slept for.
78+ let elapsed = Instant :: now ( ) . duration_since ( start) . as_millis ( ) ;
79+ Some ( (
80+ Ok :: < _ , Infallible > ( Bytes :: from ( format ! (
81+ "stream started {elapsed} millis ago\n "
82+ ) ) ) ,
83+ iters - 1 ,
84+ ) )
85+ } ;
6686
67- let mut body = responder. start_response ( Response :: new ( BodyForthcoming ) ) ;
68- let _ = write_body ( & mut body) . await ;
69- Finished :: fail ( body)
87+ Ok ( Response :: new ( Body :: from_try_stream ( unfold ( 5 , body) ) ) )
7088}
7189
72- async fn http_echo_headers ( request : Request < IncomingBody > , responder : Responder ) -> Finished {
90+ async fn http_echo ( request : Request < Body > ) -> Result < Response < Body > > {
91+ let ( _parts, body) = request. into_parts ( ) ;
92+ Ok ( Response :: new ( body) )
93+ }
94+
95+ async fn http_echo_headers ( request : Request < Body > ) -> Result < Response < Body > > {
7396 let mut response = Response :: builder ( ) ;
7497 * response. headers_mut ( ) . unwrap ( ) = request. into_parts ( ) . 0 . headers ;
75- let response = response. body ( empty ( ) ) . unwrap ( ) ;
76- responder. respond ( response) . await
98+ Ok ( response. body ( "" . to_owned ( ) . into ( ) ) ?)
99+ }
100+
101+ async fn http_echo_trailers ( request : Request < Body > ) -> Result < Response < Body > > {
102+ let collected = request. into_body ( ) . into_boxed_body ( ) . collect ( ) . await ?;
103+ let trailers = collected. trailers ( ) . cloned ( ) . unwrap_or_else ( || {
104+ let mut trailers = HeaderMap :: new ( ) ;
105+ trailers. insert ( "x-no-trailers" , "1" . parse ( ) . unwrap ( ) ) ;
106+ trailers
107+ } ) ;
108+
109+ let body = StreamBody :: new ( once_future ( async move {
110+ anyhow:: Ok ( Frame :: < Bytes > :: trailers ( trailers) )
111+ } ) ) ;
112+ Ok ( Response :: new ( Body :: from_http_body ( body) ) )
77113}
78114
79- async fn http_echo_trailers ( request : Request < IncomingBody > , responder : Responder ) -> Finished {
80- let body = responder. start_response ( Response :: new ( BodyForthcoming ) ) ;
81- let ( trailers, result) = match request. into_body ( ) . finish ( ) . await {
82- Ok ( trailers) => ( trailers, Ok ( ( ) ) ) ,
83- Err ( err) => ( Default :: default ( ) , Err ( std:: io:: Error :: other ( err) ) ) ,
115+ async fn http_response_status ( request : Request < Body > ) -> Result < Response < Body > > {
116+ let status = if let Some ( header_val) = request. headers ( ) . get ( "x-response-status" ) {
117+ header_val
118+ . to_str ( )
119+ . context ( "contents of x-response-status" ) ?
120+ . parse :: < u16 > ( )
121+ . context ( "u16 value from x-response-status" ) ?
122+ } else {
123+ 500
84124 } ;
85- Finished :: finish ( body, result, trailers)
125+ Ok ( Response :: builder ( )
126+ . status ( status)
127+ . body ( String :: new ( ) . into ( ) ) ?)
128+ }
129+
130+ async fn http_response_fail ( _request : Request < Body > ) -> Result < Response < Body > > {
131+ Err ( anyhow:: anyhow!( "error creating response" ) )
132+ }
133+
134+ async fn http_body_fail ( _request : Request < Body > ) -> Result < Response < Body > > {
135+ let body = StreamBody :: new ( once_future ( async move {
136+ Err :: < Frame < Bytes > , _ > ( anyhow:: anyhow!( "error creating body" ) )
137+ } ) ) ;
138+
139+ Ok ( Response :: new ( Body :: from_http_body ( body) ) )
86140}
87141
88- async fn http_not_found ( _request : Request < IncomingBody > , responder : Responder ) -> Finished {
142+ async fn http_not_found ( _request : Request < Body > ) -> Result < Response < Body > > {
89143 let response = Response :: builder ( )
90144 . status ( StatusCode :: NOT_FOUND )
91- . body ( empty ( ) )
145+ . body ( Body :: empty ( ) )
92146 . unwrap ( ) ;
93- responder . respond ( response) . await
147+ Ok ( response)
94148}
0 commit comments