1
+ #![ feature( async_await) ]
1
2
#![ deny( warnings) ]
2
- extern crate futures;
3
3
extern crate hyper;
4
4
extern crate pretty_env_logger;
5
5
extern crate serde_json;
6
6
7
- use futures:: { future, Future , Stream } ;
8
-
9
7
use hyper:: { Body , Chunk , Client , Method , Request , Response , Server , StatusCode , header} ;
10
8
use hyper:: client:: HttpConnector ;
11
- use hyper:: service:: service_fn;
9
+ use hyper:: service:: { service_fn, make_service_fn} ;
10
+ use futures_util:: { TryStreamExt } ;
11
+
12
+ type GenericError = Box < dyn std:: error:: Error + Send + Sync > ;
12
13
13
14
static NOTFOUND : & [ u8 ] = b"Not Found" ;
14
15
static URL : & str = "http://127.0.0.1:1337/json_api" ;
15
16
static INDEX : & [ u8 ] = b"<a href=\" test.html\" >test.html</a>" ;
16
17
static POST_DATA : & str = r#"{"original": "data"}"# ;
17
18
18
- type GenericError = Box < dyn std:: error:: Error + Send + Sync > ;
19
- type ResponseFuture = Box < dyn Future < Item =Response < Body > , Error =GenericError > + Send > ;
20
-
21
- fn client_request_response ( client : & Client < HttpConnector > ) -> ResponseFuture {
19
+ async fn client_request_response ( client : & Client < HttpConnector > )
20
+ -> Result < Response < Body > , GenericError >
21
+ {
22
22
let req = Request :: builder ( )
23
23
. method ( Method :: POST )
24
24
. uri ( URL )
25
25
. header ( header:: CONTENT_TYPE , "application/json" )
26
26
. body ( POST_DATA . into ( ) )
27
27
. unwrap ( ) ;
28
28
29
- Box :: new ( client. request ( req) . from_err ( ) . map ( |web_res| {
30
- // Compare the JSON we sent (before) with what we received (after):
31
- let body = Body :: wrap_stream ( web_res. into_body ( ) . map ( |b| {
32
- Chunk :: from ( format ! ( "<b>POST request body</b>: {}<br><b>Response</b>: {}" ,
33
- POST_DATA ,
34
- std:: str :: from_utf8( & b) . unwrap( ) ) )
35
- } ) ) ;
29
+ let web_res = client. request ( req) . await ? ;
30
+ // Compare the JSON we sent (before) with what we received (after):
31
+ let body = Body :: wrap_stream ( web_res. into_body ( ) . map_ok ( |b| {
32
+ Chunk :: from ( format ! ( "<b>POST request body</b>: {}<br><b>Response</b>: {}" ,
33
+ POST_DATA ,
34
+ std:: str :: from_utf8( & b) . unwrap( ) ) )
35
+ } ) ) ;
36
36
37
- Response :: new ( body)
38
- } ) )
37
+ Ok ( Response :: new ( body) )
39
38
}
40
39
41
- fn api_post_response ( req : Request < Body > ) -> ResponseFuture {
40
+ async fn api_post_response ( req : Request < Body > )
41
+ -> Result < Response < Body > , GenericError >
42
+ {
42
43
// A web api to run against
43
- Box :: new ( req. into_body ( )
44
- . concat2 ( ) // Concatenate all chunks in the body
45
- . from_err ( )
46
- . and_then ( |entire_body| {
47
- // TODO: Replace all unwraps with proper error handling
48
- let str = String :: from_utf8 ( entire_body. to_vec ( ) ) ?;
49
- let mut data : serde_json:: Value = serde_json:: from_str ( & str) ?;
50
- data[ "test" ] = serde_json:: Value :: from ( "test_value" ) ;
51
- let json = serde_json:: to_string ( & data) ?;
52
- let response = Response :: builder ( )
53
- . status ( StatusCode :: OK )
54
- . header ( header:: CONTENT_TYPE , "application/json" )
55
- . body ( Body :: from ( json) ) ?;
56
- Ok ( response)
57
- } )
58
- )
44
+ let entire_body = req. into_body ( ) . try_concat ( ) . await ?;
45
+ // TODO: Replace all unwraps with proper error handling
46
+ let str = String :: from_utf8 ( entire_body. to_vec ( ) ) ?;
47
+ let mut data : serde_json:: Value = serde_json:: from_str ( & str) ?;
48
+ data[ "test" ] = serde_json:: Value :: from ( "test_value" ) ;
49
+ let json = serde_json:: to_string ( & data) ?;
50
+ let response = Response :: builder ( )
51
+ . status ( StatusCode :: OK )
52
+ . header ( header:: CONTENT_TYPE , "application/json" )
53
+ . body ( Body :: from ( json) ) ?;
54
+ Ok ( response)
59
55
}
60
56
61
- fn api_get_response ( ) -> ResponseFuture {
57
+ async fn api_get_response ( ) -> Result < Response < Body > , GenericError > {
62
58
let data = vec ! [ "foo" , "bar" ] ;
63
59
let res = match serde_json:: to_string ( & data) {
64
60
Ok ( json) => {
@@ -74,59 +70,62 @@ fn api_get_response() -> ResponseFuture {
74
70
. unwrap ( )
75
71
}
76
72
} ;
77
-
78
- Box :: new ( future:: ok ( res) )
73
+ Ok ( res)
79
74
}
80
75
81
- fn response_examples ( req : Request < Body > , client : & Client < HttpConnector > ) -> ResponseFuture {
76
+ async fn response_examples ( req : Request < Body > , client : & Client < HttpConnector > )
77
+ -> Result < Response < Body > , GenericError >
78
+ {
82
79
match ( req. method ( ) , req. uri ( ) . path ( ) ) {
83
80
( & Method :: GET , "/" ) | ( & Method :: GET , "/index.html" ) => {
84
81
let body = Body :: from ( INDEX ) ;
85
- Box :: new ( future :: ok ( Response :: new ( body) ) )
82
+ Ok ( Response :: new ( body) )
86
83
} ,
87
84
( & Method :: GET , "/test.html" ) => {
88
- client_request_response ( client)
85
+ client_request_response ( client) . await
89
86
} ,
90
87
( & Method :: POST , "/json_api" ) => {
91
- api_post_response ( req)
88
+ api_post_response ( req) . await
92
89
} ,
93
90
( & Method :: GET , "/json_api" ) => {
94
- api_get_response ( )
91
+ api_get_response ( ) . await
95
92
}
96
93
_ => {
97
94
// Return 404 not found response.
98
95
let body = Body :: from ( NOTFOUND ) ;
99
- Box :: new ( future :: ok ( Response :: builder ( )
100
- . status ( StatusCode :: NOT_FOUND )
101
- . body ( body)
102
- . unwrap ( ) ) )
96
+ Ok ( Response :: builder ( )
97
+ . status ( StatusCode :: NOT_FOUND )
98
+ . body ( body)
99
+ . unwrap ( ) )
103
100
}
104
101
}
105
102
}
106
103
107
- fn main ( ) {
104
+ #[ hyper:: rt:: main]
105
+ async fn main ( ) -> Result < ( ) , GenericError > {
108
106
pretty_env_logger:: init ( ) ;
109
107
110
108
let addr = "127.0.0.1:1337" . parse ( ) . unwrap ( ) ;
111
109
112
- hyper:: rt:: run ( future:: lazy ( move || {
113
- // Share a `Client` with all `Service`s
114
- let client = Client :: new ( ) ;
110
+ // Share a `Client` with all `Service`s
111
+ let client = Client :: new ( ) ;
115
112
116
- let new_service = move || {
117
- // Move a clone of `client` into the `service_fn`.
118
- let client = client. clone ( ) ;
119
- service_fn ( move |req| {
113
+ let new_service = make_service_fn ( move |_| {
114
+ // Move a clone of `client` into the `service_fn`.
115
+ let client = client. clone ( ) ;
116
+ async {
117
+ Ok :: < _ , GenericError > ( service_fn ( move |req| {
120
118
response_examples ( req, & client)
121
- } )
122
- } ;
119
+ } ) )
120
+ }
121
+ } ) ;
123
122
124
- let server = Server :: bind ( & addr)
125
- . serve ( new_service)
126
- . map_err ( |e| eprintln ! ( "server error: {}" , e) ) ;
123
+ let server = Server :: bind ( & addr)
124
+ . serve ( new_service) ;
127
125
128
- println ! ( "Listening on http://{}" , addr) ;
126
+ println ! ( "Listening on http://{}" , addr) ;
129
127
130
- server
131
- } ) ) ;
128
+ server. await ?;
129
+
130
+ Ok ( ( ) )
132
131
}
0 commit comments