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}