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}