+20
-33
lines changedFilter options
+20
-33
lines changed Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ async-session = { version = "3.0", optional = true }
38
38
async-sse = "4.0.1"
39
39
async-std = { version = "1.6.5", features = ["unstable"] }
40
40
async-trait = "0.1.41"
41
+
cap-async-std = "0.21.1"
41
42
femme = { version = "2.1.1", optional = true }
42
43
futures-util = "0.3.6"
43
44
http-client = { version = "6.1.0", default-features = false }
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
1
1
use crate::log;
2
2
use crate::{Body, Endpoint, Request, Response, Result, StatusCode};
3
3
4
-
use async_std::path::PathBuf as AsyncPathBuf;
4
+
use async_std::io::BufReader;
5
5
6
-
use std::path::{Path, PathBuf};
7
-
use std::{ffi::OsStr, io};
6
+
use cap_async_std::fs;
8
7
9
8
pub(crate) struct ServeDir {
10
9
prefix: String,
11
-
dir: PathBuf,
10
+
dir: fs::Dir,
12
11
}
13
12
14
13
impl ServeDir {
15
14
/// Create a new instance of `ServeDir`.
16
-
pub(crate) fn new(prefix: String, dir: PathBuf) -> Self {
15
+
pub(crate) fn new(prefix: String, dir: fs::Dir) -> Self {
17
16
Self { prefix, dir }
18
17
}
19
18
}
@@ -29,33 +28,14 @@ where
29
28
.strip_prefix(&self.prefix.trim_end_matches('*'))
30
29
.unwrap();
31
30
let path = path.trim_start_matches('/');
32
-
let mut file_path = self.dir.clone();
33
-
for p in Path::new(path) {
34
-
if p == OsStr::new(".") {
35
-
continue;
36
-
} else if p == OsStr::new("..") {
37
-
file_path.pop();
38
-
} else {
39
-
file_path.push(&p);
40
-
}
41
-
}
42
-
43
-
log::info!("Requested file: {:?}", file_path);
44
-
45
-
let file_path = AsyncPathBuf::from(file_path);
46
-
if !file_path.starts_with(&self.dir) {
47
-
log::warn!("Unauthorized attempt to read: {:?}", file_path);
48
-
Ok(Response::new(StatusCode::Forbidden))
49
-
} else {
50
-
match Body::from_file(&file_path).await {
51
-
Ok(body) => Ok(Response::builder(StatusCode::Ok).body(body).build()),
52
-
Err(e) if e.kind() == io::ErrorKind::NotFound => {
53
-
log::warn!("File not found: {:?}", &file_path);
54
-
Ok(Response::new(StatusCode::NotFound))
55
-
}
56
-
Err(e) => Err(e.into()),
57
-
}
58
-
}
31
+
32
+
log::info!("Requested file: {:?}", path);
33
+
34
+
let file = self.dir.open(path).await?;
35
+
// TODO: This always uses `mime::BYTE_STREAM`; with http-types 3.0
36
+
// we'll be able to use `Body::from_open_file` which fixes this.
37
+
let body = Body::from_reader(BufReader::new(file), None);
38
+
Ok(Response::builder(StatusCode::Ok).body(body).build())
59
39
}
60
40
}
61
41
Original file line number Diff line number Diff line change
@@ -2,6 +2,9 @@ use std::fmt::Debug;
2
2
use std::io;
3
3
use std::path::Path;
4
4
use std::sync::Arc;
5
+
use async_std::task;
6
+
use cap_async_std::ambient_authority;
7
+
use cap_async_std::fs::Dir;
5
8
6
9
use crate::endpoint::MiddlewareEndpoint;
7
10
use crate::fs::{ServeDir, ServeFile};
@@ -165,7 +168,10 @@ impl<'a, State: Clone + Send + Sync + 'static> Route<'a, State> {
165
168
/// ```
166
169
pub fn serve_dir(&mut self, dir: impl AsRef<Path>) -> io::Result<()> {
167
170
// Verify path exists, return error if it doesn't.
168
-
let dir = dir.as_ref().to_owned().canonicalize()?;
171
+
let path = dir.as_ref().to_owned().canonicalize()?;
172
+
let dir = task::block_on(async {
173
+
Dir::open_ambient_dir(path, ambient_authority()).await
174
+
})?;
169
175
let prefix = self.path().to_string();
170
176
self.get(ServeDir::new(prefix, dir));
171
177
Ok(())
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4