salvo_serve_static/file.rs
1use std::path::PathBuf;
2
3use salvo_core::fs::{NamedFile, NamedFileBuilder};
4use salvo_core::http::{Request, Response, StatusError};
5use salvo_core::{Depot, FlowCtrl, Handler, Writer, async_trait};
6
7/// `StaticFile` is a handler that serves a single static file.
8///
9/// # Examples
10///
11/// ```
12/// use salvo_core::prelude::*;
13/// use salvo_serve_static::StaticFile;
14///
15/// #[handler]
16/// async fn hello() -> &'static str {
17/// "Hello World"
18/// }
19///
20/// let router = Router::new()
21/// .get(hello)
22/// .push(Router::with_path("favicon.ico").get(StaticFile::new("assets/favicon.ico")));
23/// ```
24#[derive(Clone)]
25pub struct StaticFile(NamedFileBuilder);
26
27impl StaticFile {
28 /// Create a new `StaticFile` handler.
29 #[inline]
30 pub fn new(path: impl Into<PathBuf>) -> Self {
31 StaticFile(NamedFile::builder(path))
32 }
33
34 /// Set the chunk size for file reading.
35 ///
36 /// During file reading, the maximum read size at one time will affect the
37 /// access experience and memory usage of the server.
38 ///
39 /// Please set it according to your specific requirements.
40 ///
41 /// The default is 1MB.
42 #[inline]
43 pub fn chunk_size(self, size: u64) -> Self {
44 Self(self.0.buffer_size(size))
45 }
46}
47
48#[async_trait]
49impl Handler for StaticFile {
50 #[inline]
51 async fn handle(
52 &self,
53 req: &mut Request,
54 depot: &mut Depot,
55 res: &mut Response,
56 ctrl: &mut FlowCtrl,
57 ) {
58 match self.0.clone().build().await {
59 Ok(file) => file.write(req, depot, res).await,
60 Err(_) => {
61 res.render(StatusError::not_found());
62 }
63 }
64 ctrl.skip_rest();
65 }
66}