Skip to content

Commit 2be1e53

Browse files
committed
Fix test issue on Windows, adjust API
Changes `File` to contain the full `Origin` uri from the request, so normalize_dir doesn't have to deal with platform specific behavior. This is also a more convient way to handle Redirects, as well as provide more consistent access to the query parameters.
1 parent bfb3285 commit 2be1e53

File tree

1 file changed

+27
-14
lines changed

1 file changed

+27
-14
lines changed

core/lib/src/fs/server.rs

+27-14
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ use std::sync::Arc;
55

66
use crate::fs::NamedFile;
77
use crate::{Data, Request, outcome::IntoOutcome};
8-
use crate::http::{Method, HeaderMap, Header, uri::{Segments, Reference}, Status};
8+
use crate::http::{
9+
Method,
10+
HeaderMap,
11+
Header,
12+
uri::{Segments, Origin},
13+
Status,
14+
ext::IntoOwned,
15+
};
916
use crate::route::{Route, Handler, Outcome};
1017
use crate::response::{Redirect, Responder};
1118

@@ -117,9 +124,9 @@ pub trait Rewriter: Send + Sync + 'static {
117124
pub enum FileResponse<'p, 'h> {
118125
/// Return the contents of the specified file.
119126
File(File<'p, 'h>),
120-
/// Returns a Redirect to the specified path. This will be appended to the
121-
/// [`FileServer`]'s base uri, so the redirect uri is relative to wherever
122-
/// the [`FileServer`] is mounted.
127+
/// Returns a Redirect to the specified path. This needs to be an absolute
128+
/// URI, so you should start with [`File.full_uri`](File) when constructing
129+
/// a redirect.
123130
Redirect(Redirect),
124131
}
125132

@@ -150,8 +157,8 @@ impl<'p, 'h> From<Redirect> for Option<FileResponse<'p, 'h>> {
150157
pub struct File<'p, 'h> {
151158
/// The path to the file that [`FileServer`] will respond with.
152159
pub path: Cow<'p, Path>,
153-
/// The original path this File started out with.
154-
pub starting_path: &'p Path,
160+
/// The original uri from the [`Request`]
161+
pub full_uri: &'p Origin<'p>,
155162
/// A list of headers to be added to the generated response.
156163
pub headers: HeaderMap<'h>,
157164
}
@@ -167,7 +174,7 @@ impl<'p, 'h> File<'p, 'h> {
167174
pub fn with_path(self, path: impl Into<Cow<'p, Path>>) -> Self {
168175
Self {
169176
path: path.into(),
170-
starting_path: self.starting_path,
177+
full_uri: self.full_uri,
171178
headers: self.headers,
172179
}
173180
}
@@ -176,10 +183,17 @@ impl<'p, 'h> File<'p, 'h> {
176183
pub fn map_path<R: Into<Cow<'p, Path>>>(self, f: impl FnOnce(Cow<'p, Path>) -> R) -> Self {
177184
Self {
178185
path: f(self.path).into(),
179-
starting_path: self.starting_path,
186+
full_uri: self.full_uri,
180187
headers: self.headers,
181188
}
182189
}
190+
191+
/// Convert this `File` into a Redirect, transforming the URI.
192+
pub fn into_redirect(self, f: impl FnOnce(Origin<'static>) -> Origin<'static>)
193+
-> FileResponse<'p, 'h>
194+
{
195+
FileResponse::Redirect(Redirect::permanent(f(self.full_uri.clone().into_owned())))
196+
}
183197
}
184198

185199
impl<F: Send + Sync + 'static> Rewriter for F
@@ -339,8 +353,9 @@ pub fn filter_dotfiles(file: &File<'_, '_>) -> bool {
339353
/// # }
340354
/// ```
341355
pub fn normalize_dirs<'p, 'h>(file: File<'p, 'h>) -> FileResponse<'p, 'h> {
342-
if file.path.is_dir() && !file.path.as_os_str().as_encoded_bytes().ends_with(b"/") {
343-
FileResponse::Redirect(Redirect::permanent(format!("{}/", file.starting_path.display())))
356+
if !file.full_uri.has_trailing_slash() && file.path.is_dir() {
357+
// Known good path + '/' is a good path
358+
file.into_redirect(|o| o.map_path(|p| format!("{p}/")).unwrap())
344359
} else {
345360
FileResponse::File(file)
346361
}
@@ -521,7 +536,7 @@ impl Handler for FileServer {
521536
.and_then(|segments| segments.to_path_buf(true).ok());
522537
let mut response = path.as_ref().map(|p| FileResponse::File(File {
523538
path: Cow::Borrowed(p),
524-
starting_path: p,
539+
full_uri: req.uri(),
525540
headers: HeaderMap::new(),
526541
}));
527542

@@ -538,9 +553,7 @@ impl Handler for FileServer {
538553
}).or_forward((data, Status::NotFound))
539554
},
540555
Some(FileResponse::Redirect(r)) => {
541-
let base = req.route().unwrap().uri.base();
542-
r.map_uri(|u| Reference::parse_owned(format!("{}/{}", base, u)).unwrap())
543-
.respond_to(req)
556+
r.respond_to(req)
544557
.or_forward((data, Status::InternalServerError))
545558
},
546559
_ => Outcome::forward(data, Status::NotFound),

0 commit comments

Comments
 (0)