Skip to content

Commit ea8dffe

Browse files
authored
docs(examples): Improved send_file.rs example to use streaming. (#3433)
1 parent d48528d commit ea8dffe

File tree

2 files changed

+34
-12
lines changed

2 files changed

+34
-12
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ tokio = { version = "1", features = [
5959
"test-util",
6060
] }
6161
tokio-test = "0.4"
62+
tokio-util = "0.7.10"
6263

6364
[features]
6465
# Nothing by default

examples/send_file.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
use std::net::SocketAddr;
44

5-
use hyper::server::conn::http1;
6-
use tokio::net::TcpListener;
7-
85
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;
1010
use hyper::service::service_fn;
1111
use hyper::{Method, Request, Response, Result, StatusCode};
12+
use tokio::{fs::File, net::TcpListener};
13+
use tokio_util::io::ReaderStream;
1214

1315
#[path = "../benches/support/mod.rs"]
1416
mod support;
@@ -41,7 +43,9 @@ async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
4143
}
4244
}
4345

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>>> {
4549
match (req.method(), req.uri().path()) {
4650
(&Method::GET, "/") | (&Method::GET, "/index.html") => simple_file_send(INDEX).await,
4751
(&Method::GET, "/no_file.html") => {
@@ -53,18 +57,35 @@ async fn response_examples(req: Request<hyper::body::Incoming>) -> Result<Respon
5357
}
5458

5559
/// HTTP status code 404
56-
fn not_found() -> Response<Full<Bytes>> {
60+
fn not_found() -> Response<BoxBody<Bytes, std::io::Error>> {
5761
Response::builder()
5862
.status(StatusCode::NOT_FOUND)
59-
.body(Full::new(NOTFOUND.into()))
63+
.body(Full::new(NOTFOUND.into()).map_err(|e| match e {}).boxed())
6064
.unwrap()
6165
}
6266

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());
6773
}
6874

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)
7091
}

0 commit comments

Comments
 (0)