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, Debug)]
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        Self(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    #[must_use]
44    pub fn chunk_size(self, size: u64) -> Self {
45        Self(self.0.buffer_size(size))
46    }
47}
48
49#[async_trait]
50impl Handler for StaticFile {
51    #[inline]
52    async fn handle(
53        &self,
54        req: &mut Request,
55        depot: &mut Depot,
56        res: &mut Response,
57        ctrl: &mut FlowCtrl,
58    ) {
59        match self.0.clone().build().await {
60            Ok(file) => file.write(req, depot, res).await,
61            Err(_) => {
62                res.render(StatusError::not_found());
63            }
64        }
65        ctrl.skip_rest();
66    }
67}