Skip to content

Commit

Permalink
Updates based on PR review
Browse files Browse the repository at this point in the history
- `Rewrite` and `Rewriter` are no longer re-exported from `fs`.
- Renamed `FileServer::directory` to `FileServer::new_without_index`.
- Added missing documentation in a number of places.
  • Loading branch information
the10thWiz authored and SergioBenitez committed Jul 6, 2024
1 parent 113b79c commit 482a047
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 24 deletions.
1 change: 0 additions & 1 deletion core/lib/src/fs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ pub use server::*;
pub use named_file::*;
pub use temp_file::*;
pub use file_name::*;
pub use rewrite::{Rewrite, Rewriter};

crate::export! {
/// Generates a crate-relative version of a path.
Expand Down
28 changes: 20 additions & 8 deletions core/lib/src/fs/rewrite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@ use crate::response::Redirect;
/// with the file contents, if [`Rewrite::File`] is specified, or a redirect, if
/// [`Rewrite::Redirect`] is specified.
///
/// # Creating a `FileServer`
/// # Creating a [`FileServer`]
///
/// The primary way to create a `FileServer` is via [`FileServer::new()`] which
/// creates a new `FileServer` with a default set of `Rewriter`s: a filter for
/// The primary way to create a [`FileServer`] is via [`FileServer::new()`] which
/// creates a new [`FileServer`] with a default set of `Rewriter`s: a filter for
/// dotfiles, a root path to apply as a prefix, an index file rewriter, and a
/// rewriter to normalize directories to always include a trailing slash.
///
/// [`FileServer`]: super::FileServer
/// [`FileServer::new()`]: super::FileServer::new
pub trait Rewriter: Send + Sync + 'static {
/// Alter the [`Rewrite`] as needed.
fn rewrite<'r>(&self, opt: Option<Rewrite<'r>>, req: &'r Request<'_>) -> Option<Rewrite<'r>>;
}

/// A Response from a [`FileServer`]
/// A Response from a [`FileServer`](super::FileServer)
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum Rewrite<'r> {
Expand All @@ -36,20 +39,27 @@ pub enum Rewrite<'r> {
Redirect(Redirect),
}

/// A File response from a [`FileServer`] and a rewriter.
/// A File response from a [`FileServer`](super::FileServer) and a rewriter.
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct File<'r> {
/// The path to the file that [`FileServer`] will respond with.
/// The path to the file that [`FileServer`](super::FileServer) will respond with.
pub path: Cow<'r, Path>,
/// A list of headers to be added to the generated response.
pub headers: HeaderMap<'r>,
}

impl<'r> File<'r> {
/// A new `File`, with not additional headers.
pub fn new(path: impl Into<Cow<'r, Path>>) -> Self {
Self { path: path.into(), headers: HeaderMap::new() }
}

/// A new `File`, with not additional headers.
///
/// # Panics
///
/// Panics if the `path` does not exist.
pub fn checked<P: AsRef<Path>>(path: P) -> Self {
let path = path.as_ref();
if !path.exists() {
Expand Down Expand Up @@ -79,7 +89,7 @@ impl<'r> File<'r> {
/// # Windows Note
///
/// This does *not* check the file metadata on any platform, so hidden files
/// on Windows will not be detected.
/// on Windows will not be detected by this method.
pub fn is_hidden(&self) -> bool {
self.path.iter().any(|s| s.as_encoded_bytes().starts_with(b"."))
}
Expand Down Expand Up @@ -180,7 +190,7 @@ impl Rewriter for TrailingDirs {
/// use rocket::fs::FileServer;
/// use rocket::fs::rewrite::DirIndex;
///
/// FileServer::directory("static")
/// FileServer::new_without_index("static")
/// .rewrite(DirIndex::if_exists("index.htm"))
/// .rewrite(DirIndex::unconditional("index.html"));
/// ```
Expand All @@ -190,10 +200,12 @@ pub struct DirIndex {
}

impl DirIndex {
/// Appends `path` to every request for a directory.
pub fn unconditional(path: impl AsRef<Path>) -> Self {
Self { path: path.as_ref().to_path_buf(), check: false }
}

/// Only appends `path` to a request for a directory if the file exists.
pub fn if_exists(path: impl AsRef<Path>) -> Self {
Self { path: path.as_ref().to_path_buf(), check: true }
}
Expand Down
87 changes: 72 additions & 15 deletions core/lib/src/fs/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,22 @@ impl FileServer {
/// `path` with a default rank.
///
/// Adds a set of default rewrites:
/// - [`filter_dotfiles`]: Hides all dotfiles.
/// - [`prefix(path)`](prefix): Applies the root path.
/// - [`normalize_dirs`]: Normalizes directories to have a trailing slash.
/// - [`index("index.html")`](index): Appends `index.html` to directory requests.
/// - `|f, _| f.is_visible()`: Hides all dotfiles.
/// - [`Prefix::checked(path)`]: Applies the root path.
/// - [`TrailingDirs`]: Normalizes directories to have a trailing slash.
/// - [`DirIndex::unconditional("index.html")`](DirIndex::unconditional):
/// Appends `index.html` to directory requests.
///
/// If you don't want to serve requests for directories, or want to
/// customize what files are served when a directory is requested, see
/// [`Self::new_without_index`].
///
/// If you need to allow requests for dotfiles, or make any other changes
/// to the default rewrites, see [`Self::empty`].
///
/// [`Prefix::checked(path)`]: crate::fs::rewrite::Prefix::checked
/// [`TrailingDirs`]: crate::fs::rewrite::TrailingDirs
/// [`DirIndex::unconditional`]: crate::fs::DirIndex::unconditional
pub fn new<P: AsRef<Path>>(path: P) -> Self {
Self::empty()
.filter(|f, _| f.is_visible())
Expand All @@ -95,22 +107,48 @@ impl FileServer {
}

/// Constructs a new `FileServer` that serves files from the file system
/// `path` with a default rank.
/// `path` with a default rank. This variant does not add a default
/// directory index option.
///
/// Adds a set of default rewrites:
/// - [`filter_dotfiles`]: Hides all dotfiles.
/// - [`prefix(path)`](prefix): Applies the root path.
/// - [`normalize_dirs`]: Normalizes directories to have a trailing slash.
pub fn directory<P: AsRef<Path>>(path: P) -> Self {
/// - `|f, _| f.is_visible()`: Hides all dotfiles.
/// - [`Prefix::checked(path)`]: Applies the root path.
/// - [`TrailingDirs`]: Normalizes directories to have a trailing slash.
///
/// In most cases, [`Self::new`] is good enough. However, if you do not want
/// to automatically respond to requests for directories with `index.html`,
/// this method is provided.
///
/// # Example
///
/// Constructs a default file server to server files from `./static`, but
/// uses `index.txt` if `index.html` doesn't exist.
///
/// ```rust,no_run
/// # #[macro_use] extern crate rocket;
/// use rocket::fs::{FileServer, rewrite::DirIndex};
///
/// #[launch]
/// fn rocket() -> _ {
/// let server = FileServer::new("static")
/// .rewrite(DirIndex::if_exists("index.html"))
/// .rewrite(DirIndex::unconditional("index.txt"));
///
/// rocket::build()
/// .mount("/", server)
/// }
/// ```
///
/// [`Prefix::checked(path)`]: crate::fs::rewrite::Prefix::checked
/// [`TrailingDirs`]: crate::fs::rewrite::TrailingDirs
pub fn new_without_index<P: AsRef<Path>>(path: P) -> Self {
Self::empty()
.filter(|f, _| f.is_visible())
.rewrite(Prefix::checked(path))
.rewrite(TrailingDirs)
}

/// Constructs a new `FileServer`, with default rank, and no rewrites.
///
/// See [`FileServer::empty_ranked()`].
pub fn empty() -> Self {
Self {
rewrites: vec![],
Expand All @@ -127,7 +165,7 @@ impl FileServer {
/// # fn make_server() -> FileServer {
/// FileServer::empty()
/// .rank(5)
/// }
/// # }
pub fn rank(mut self, rank: isize) -> Self {
self.rank = rank;
self
Expand All @@ -140,7 +178,7 @@ impl FileServer {
/// Redirects all requests that have been filtered to the root of the `FileServer`.
///
/// ```rust,no_run
/// # use rocket::fs::{FileServer, Rewrite};
/// # use rocket::fs::{FileServer, rewrite::Rewrite};
/// # use rocket::{response::Redirect, uri, Build, Rocket, Request};
/// fn redir_missing<'r>(p: Option<Rewrite<'r>>, _req: &Request<'_>) -> Option<Rewrite<'r>> {
/// match p {
Expand Down Expand Up @@ -169,7 +207,7 @@ impl FileServer {
/// Filter out all paths with a filename of `hidden`.
///
/// ```rust,no_run
/// #[macro_use] extern crate rocket;
/// # #[macro_use] extern crate rocket;
/// use rocket::fs::FileServer;
///
/// #[launch]
Expand All @@ -179,7 +217,7 @@ impl FileServer {
///
/// rocket::build()
/// .mount("/", server)
/// # }
/// }
/// ```
pub fn filter<F: Send + Sync + 'static>(self, f: F) -> Self
where F: Fn(&File<'_>, &Request<'_>) -> bool
Expand All @@ -200,6 +238,25 @@ impl FileServer {
self.rewrite(Filter(f))
}

/// Change what files this `FileServer` will respond with
///
/// # Example
///
/// Append `index.txt` to every path.
///
/// ```rust,no_run
/// # #[macro_use] extern crate rocket;
/// use rocket::fs::FileServer;
///
/// #[launch]
/// fn rocket() -> _ {
/// let server = FileServer::new("static")
/// .map(|f, _| f.map_path(|p| p.join("index.txt")).into());
///
/// rocket::build()
/// .mount("/", server)
/// }
/// ```
pub fn map<F: Send + Sync + 'static>(self, f: F) -> Self
where F: for<'r> Fn(File<'r>, &Request<'_>) -> Rewrite<'r>
{
Expand Down

0 comments on commit 482a047

Please sign in to comment.