2
2
3
3
use std:: net:: SocketAddr ;
4
4
5
- use hyper:: server:: conn:: http1;
6
- use tokio:: net:: TcpListener ;
7
-
8
5
use bytes:: Bytes ;
9
- use http_body_util:: Full ;
6
+ use futures_util:: TryStreamExt ;
7
+ use http_body_util:: { combinators:: BoxBody , BodyExt , Full , StreamBody } ;
8
+ use hyper:: body:: Frame ;
9
+ use hyper:: server:: conn:: http1;
10
10
use hyper:: service:: service_fn;
11
11
use hyper:: { Method , Request , Response , Result , StatusCode } ;
12
+ use tokio:: { fs:: File , net:: TcpListener } ;
13
+ use tokio_util:: io:: ReaderStream ;
12
14
13
15
#[ path = "../benches/support/mod.rs" ]
14
16
mod support;
@@ -41,7 +43,9 @@ async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
41
43
}
42
44
}
43
45
44
- async fn response_examples ( req : Request < hyper:: body:: Incoming > ) -> Result < Response < Full < Bytes > > > {
46
+ async fn response_examples (
47
+ req : Request < hyper:: body:: Incoming > ,
48
+ ) -> Result < Response < BoxBody < Bytes , std:: io:: Error > > > {
45
49
match ( req. method ( ) , req. uri ( ) . path ( ) ) {
46
50
( & Method :: GET , "/" ) | ( & Method :: GET , "/index.html" ) => simple_file_send ( INDEX ) . await ,
47
51
( & Method :: GET , "/no_file.html" ) => {
@@ -53,18 +57,35 @@ async fn response_examples(req: Request<hyper::body::Incoming>) -> Result<Respon
53
57
}
54
58
55
59
/// HTTP status code 404
56
- fn not_found ( ) -> Response < Full < Bytes > > {
60
+ fn not_found ( ) -> Response < BoxBody < Bytes , std :: io :: Error > > {
57
61
Response :: builder ( )
58
62
. status ( StatusCode :: NOT_FOUND )
59
- . body ( Full :: new ( NOTFOUND . into ( ) ) )
63
+ . body ( Full :: new ( NOTFOUND . into ( ) ) . map_err ( |e| match e { } ) . boxed ( ) )
60
64
. unwrap ( )
61
65
}
62
66
63
- async fn simple_file_send ( filename : & str ) -> Result < Response < Full < Bytes > > > {
64
- if let Ok ( contents) = tokio:: fs:: read ( filename) . await {
65
- let body = contents. into ( ) ;
66
- return Ok ( Response :: new ( Full :: new ( body) ) ) ;
67
+ async fn simple_file_send ( filename : & str ) -> Result < Response < BoxBody < Bytes , std:: io:: Error > > > {
68
+ // Open file for reading
69
+ let file = File :: open ( filename) . await ;
70
+ if file. is_err ( ) {
71
+ eprintln ! ( "ERROR: Unable to open file." ) ;
72
+ return Ok ( not_found ( ) ) ;
67
73
}
68
74
69
- Ok ( not_found ( ) )
75
+ let file: File = file. unwrap ( ) ;
76
+
77
+ // Wrap to a tokio_util::io::ReaderStream
78
+ let reader_stream = ReaderStream :: new ( file) ;
79
+
80
+ // Convert to http_body_util::BoxBody
81
+ let stream_body = StreamBody :: new ( reader_stream. map_ok ( Frame :: data) ) ;
82
+ let boxed_body = stream_body. boxed ( ) ;
83
+
84
+ // Send response
85
+ let response = Response :: builder ( )
86
+ . status ( StatusCode :: OK )
87
+ . body ( boxed_body)
88
+ . unwrap ( ) ;
89
+
90
+ Ok ( response)
70
91
}
0 commit comments