1use std::path::PathBuf;
4
5use tokio::fs;
6
7use crate::core::{HttpService, HttpResult, HttpRead};
8use crate::reqres::{res, HttpRequest, HttpMethod, StatusCode};
9use crate::util::path;
10
11pub struct FilesService {
13 pub path: PathBuf,
14}
15
16impl FilesService {
17 pub fn new(path: impl Into<PathBuf>) -> FilesService {
18 FilesService { path: path.into() }
19 }
20}
21
22impl HttpService for FilesService {
23 async fn request(&self, route: &str, req: &HttpRequest, _body: &mut dyn HttpRead) -> HttpResult {
24 let path = self.path.join(path::sanitize(route)?);
25
26 let metadata = fs::metadata(&path).await?;
27
28 if metadata.is_dir() {
29 Err(StatusCode::NOT_FOUND.into())
30 } else {
31 res::file(req, &path).await
32 }
33 }
34
35 fn filter(&self, _route: &str, req: &HttpRequest) -> HttpResult<()> {
36 if req.method != HttpMethod::Get && req.method != HttpMethod::Head {
37 return Err(StatusCode::METHOD_NOT_ALLOWED.into());
38 }
39 if req.len > 0 { return Err(StatusCode::REQUEST_ENTITY_TOO_LARGE.into()); }
40 Ok(())
41 }
42}