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;
3+ use http_body_util:: { BodyExt , StreamBody } ;
4+ use wstd:: http:: body:: { Body , Bytes , Frame , Incoming } ;
5+ use wstd:: http:: { Error , HeaderMap , Request , Response , StatusCode } ;
56use wstd:: time:: { Duration , Instant } ;
67
78#[ 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 ,
9+ async fn main ( request : Request < Incoming > ) -> Result < Response < Body > , Error > {
10+ let path = request. uri ( ) . path_and_query ( ) . unwrap ( ) . as_str ( ) ;
11+ println ! ( "serving {path}" ) ;
12+ match path {
13+ "/" => http_home ( request) . await ,
14+ "/wait-response" => http_wait_response ( request) . await ,
15+ "/wait-body" => http_wait_body ( request) . await ,
16+ "/echo" => http_echo ( request) . await ,
17+ "/echo-headers" => http_echo_headers ( request) . await ,
18+ "/echo-trailers" => http_echo_trailers ( request) . await ,
19+ "/response-status" => http_response_status ( request) . await ,
20+ "/response-fail" => http_response_fail ( request) . await ,
21+ "/response-body-fail" => http_body_fail ( request) . await ,
22+ _ => http_not_found ( request) . await ,
1823 }
1924}
2025
21- async fn http_home ( _request : Request < IncomingBody > , responder : Responder ) -> Finished {
26+ async fn http_home ( _request : Request < Incoming > ) -> Result < Response < Body > > {
2227 // 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
28+ Ok ( Response :: new (
29+ "Hello, wasi:http/proxy world!\n " . to_owned ( ) . into ( ) ,
30+ ) )
2631}
2732
28- async fn http_wait ( _request : Request < IncomingBody > , responder : Responder ) -> Finished {
33+ async fn http_wait_response ( _request : Request < Incoming > ) -> Result < Response < Body > > {
2934 // Get the time now
3035 let now = Instant :: now ( ) ;
3136
@@ -35,60 +40,85 @@ async fn http_wait(_request: Request<IncomingBody>, responder: Responder) -> Fin
3540 // Compute how long we slept for.
3641 let elapsed = Instant :: now ( ) . duration_since ( now) . as_millis ( ) ;
3742
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 )
43+ Ok ( Response :: new (
44+ format ! ( "slept for {elapsed} millis\n " ) . into ( ) ,
45+ ) )
4446}
4547
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- }
48+ async fn http_wait_body ( _request : Request < Incoming > ) -> Result < Response < Body > > {
49+ // Get the time now
50+ let now = Instant :: now ( ) ;
5251
53- async fn http_fail ( _request : Request < IncomingBody > , responder : Responder ) -> Finished {
54- let body = responder. start_response ( Response :: new ( BodyForthcoming ) ) ;
55- Finished :: fail ( body)
56- }
52+ let body = StreamBody :: new ( once_future ( async move {
53+ // Sleep for one second.
54+ wstd:: task:: sleep ( Duration :: from_secs ( 1 ) ) . await ;
5755
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 ?;
62- }
63- body. flush ( ) . await ?;
64- Ok ( ( ) )
65- }
56+ // Compute how long we slept for.
57+ let elapsed = Instant :: now ( ) . duration_since ( now) . as_millis ( ) ;
58+ anyhow:: Ok ( Frame :: data ( Bytes :: from ( format ! (
59+ "slept for {elapsed} millis\n "
60+ ) ) ) )
61+ } ) ) ;
62+
63+ Ok ( Response :: new ( body. into ( ) ) )
64+ }
6665
67- let mut body = responder . start_response ( Response :: new ( BodyForthcoming ) ) ;
68- let _ = write_body ( & mut body) . await ;
69- Finished :: fail ( body)
66+ async fn http_echo ( request : Request < Incoming > ) -> Result < Response < Body > > {
67+ let ( _parts , body) = request . into_parts ( ) ;
68+ Ok ( Response :: new ( body. into ( ) ) )
7069}
7170
72- async fn http_echo_headers ( request : Request < IncomingBody > , responder : Responder ) -> Finished {
71+ async fn http_echo_headers ( request : Request < Incoming > ) -> Result < Response < Body > > {
7372 let mut response = Response :: builder ( ) ;
7473 * response. headers_mut ( ) . unwrap ( ) = request. into_parts ( ) . 0 . headers ;
75- let response = response. body ( empty ( ) ) . unwrap ( ) ;
76- responder. respond ( response) . await
74+ Ok ( response. body ( "" . to_owned ( ) . into ( ) ) ?)
7775}
7876
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) ) ) ,
77+ async fn http_echo_trailers ( request : Request < Incoming > ) -> Result < Response < Body > > {
78+ let collected = request. into_body ( ) . into_http_body ( ) . collect ( ) . await ?;
79+ let trailers = collected. trailers ( ) . cloned ( ) . unwrap_or_else ( || {
80+ let mut trailers = HeaderMap :: new ( ) ;
81+ trailers. insert ( "x-no-trailers" , "1" . parse ( ) . unwrap ( ) ) ;
82+ trailers
83+ } ) ;
84+
85+ let body = StreamBody :: new ( once_future ( async move {
86+ anyhow:: Ok ( Frame :: < Bytes > :: trailers ( trailers) )
87+ } ) ) ;
88+ Ok ( Response :: new ( body. into ( ) ) )
89+ }
90+
91+ async fn http_response_status ( request : Request < Incoming > ) -> Result < Response < Body > > {
92+ let status = if let Some ( header_val) = request. headers ( ) . get ( "x-response-status" ) {
93+ header_val
94+ . to_str ( )
95+ . context ( "contents of x-response-status" ) ?
96+ . parse :: < u16 > ( )
97+ . context ( "u16 value from x-response-status" ) ?
98+ } else {
99+ 500
84100 } ;
85- Finished :: finish ( body, result, trailers)
101+ Ok ( Response :: builder ( )
102+ . status ( status)
103+ . body ( String :: new ( ) . into ( ) ) ?)
104+ }
105+
106+ async fn http_response_fail ( _request : Request < Incoming > ) -> Result < Response < Body > > {
107+ Err ( anyhow:: anyhow!( "error creating response" ) )
108+ }
109+
110+ async fn http_body_fail ( _request : Request < Incoming > ) -> Result < Response < Body > > {
111+ let body = StreamBody :: new ( once_future ( async move {
112+ Err :: < Frame < Bytes > , _ > ( anyhow:: anyhow!( "error creating body" ) )
113+ } ) ) ;
114+
115+ Ok ( Response :: new ( body. into ( ) ) )
86116}
87117
88- async fn http_not_found ( _request : Request < IncomingBody > , responder : Responder ) -> Finished {
118+ async fn http_not_found ( _request : Request < Incoming > ) -> Result < Response < Body > > {
89119 let response = Response :: builder ( )
90120 . status ( StatusCode :: NOT_FOUND )
91- . body ( empty ( ) )
121+ . body ( Body :: empty ( ) )
92122 . unwrap ( ) ;
93- responder . respond ( response) . await
123+ Ok ( response)
94124}
0 commit comments