index : static-web-server.git

ascending towards madness

author Jose Quintana <joseluisquintana20@gmail.com> 2021-02-14 22:18:13.0 +00:00:00
committer Jose Quintana <joseluisquintana20@gmail.com> 2021-02-14 22:18:13.0 +00:00:00
commit
5fed730516005f9c494fb3ba6edc782647963a0e [patch]
tree
33b6f97d688d802af21b133d37cf181fc9d8239d
parent
a664866f09695fef1a3d7016611d202c858fdb6c
download
5fed730516005f9c494fb3ba6edc782647963a0e.tar.gz

refactor: minor error handling tweaks on directory listing feature



Diff

 src/helpers.rs                          | 19 ++++++++---------
 src/staticfile_middleware/staticfile.rs | 37 ++++++++++++++++++++++------------
 2 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/src/helpers.rs b/src/helpers.rs
index f8b1713..99921c0 100644
--- a/src/helpers.rs
+++ b/src/helpers.rs
@@ -2,16 +2,15 @@ use std::error;
use std::path::{Path, PathBuf};

/// Validate and return a directory path.
pub fn get_valid_dirpath<P: AsRef<Path>>(path: P) -> Result<PathBuf, Box<dyn error::Error>>
pub fn get_valid_dirpath<P: AsRef<Path>>(p: P) -> Result<PathBuf, Box<dyn error::Error>>
where
    PathBuf: From<P>,
{
    match PathBuf::from(path) {
        v if !v.exists() => Result::Err(From::from(format!("path \"{:?}\" was not found", &v))),
        v if !v.is_dir() => {
            Result::Err(From::from(format!("path \"{:?}\" is not a directory", &v)))
        }
        v => Result::Ok(v),
    let p: PathBuf = p.into();
    match p {
        v if !v.exists() => Err(From::from(format!("path \"{:?}\" was not found", &v))),
        v if !v.is_dir() => Err(From::from(format!("path \"{:?}\" is not a directory", &v))),
        v => Ok(v),
    }
}

@@ -21,13 +20,13 @@ where
    PathBuf: From<P>,
{
    let path = match get_valid_dirpath(path) {
        Err(e) => return Result::Err(e),
        Ok(v) => v,
        Err(e) => return Err(e),
    };

    match path.iter().last() {
        Some(v) => Result::Ok(v.to_str().unwrap().to_string()),
        _ => Result::Err(From::from(format!(
        Some(v) => Ok(v.to_str().unwrap().to_string()),
        None => Err(From::from(format!(
            "directory name for path \"{:?}\" was not determined",
            path,
        ))),
diff --git a/src/staticfile_middleware/staticfile.rs b/src/staticfile_middleware/staticfile.rs
index 4df9ff8..a2a84f4 100644
--- a/src/staticfile_middleware/staticfile.rs
+++ b/src/staticfile_middleware/staticfile.rs
@@ -40,12 +40,13 @@ impl Staticfile {
        })
    }

    /// Resolve a specific path which should be relative to base path.
    fn resolve_path(&self, path: &[&str]) -> Result<PathBuf, Box<dyn error::Error>> {
        let current_dirname = percent_decode_str(path[0]).decode_utf8()?;
        let asserts_dirname = self.assets.iter().last().unwrap().to_str().unwrap();
        let mut is_assets = false;

        let path_resolved = if current_dirname.as_ref() == asserts_dirname {
        let path_resolved = if current_dirname == asserts_dirname {
            // Assets path validation resolve
            is_assets = true;

@@ -91,7 +92,7 @@ impl Handler for Staticfile {

        // Resolve path on file system
        let path_resolved = match self.resolve_path(&req.url.path()) {
            Ok(file_path) => file_path,
            Ok(p) => p,
            Err(e) => {
                trace!("{}", e);
                return Ok(Response::with(status::NotFound));
@@ -100,13 +101,13 @@ impl Handler for Staticfile {

        // 1. Check if "directory listing" feature is enabled,
        // if current path is a valid directory and
        // if it does not contain an index.html file
        // if it does not contain an `index.html` file
        if self.dir_listing && path_resolved.is_dir() && !path_resolved.join("index.html").exists()
        {
            let read_dir = match std::fs::read_dir(path_resolved) {
                Ok(dir) => dir,
                Err(err) => {
                    error!("{}", err);
            let read_dir = match std::fs::read_dir(&path_resolved) {
                Ok(d) => d,
                Err(e) => {
                    error!("{}", e);
                    return Ok(Response::with(status::InternalServerError));
                }
            };
@@ -118,13 +119,19 @@ impl Handler for Staticfile {
                .map(|i| format!("/{}", i))
                .collect::<String>();

            // Redirect if current path does not end with slash
            // Redirect if current path does not end with a slash
            if !current_path.ends_with('/') {
                let mut u: url::Url = req.url.clone().into();
                current_path.push('/');
                u.set_path(&current_path);

                let url = iron::Url::from_generic_url(u).expect("Unable to parse redirect url");
                let url = match iron::Url::from_generic_url(u) {
                    Ok(u) => u,
                    Err(e) => {
                        error!("Unable to parse redirection url: {}", e);
                        return Ok(Response::with(status::BadRequest));
                    }
                };

                return Ok(Response::with((
                    status::PermanentRedirect,
@@ -132,7 +139,7 @@ impl Handler for Staticfile {
                )));
            }

            // Read current directory and create the index page
            // Read current directory and create the index page content
            let mut entries_str = String::new();
            if current_path != "/" {
                entries_str =
@@ -187,7 +194,7 @@ impl Handler for Staticfile {
        // 2. Otherwise proceed with the normal file-  process

        // Search a file and its metadata by the resolved path
        let static_file = match StaticFileWithMeta::search(path_resolved.clone()) {
        let static_file = match StaticFileWithMeta::search(&path_resolved) {
            Ok(f) => f,
            Err(e) => {
                trace!("{}", e);
@@ -262,8 +269,12 @@ struct StaticFileWithMeta {
impl StaticFileWithMeta {
    /// Search for a regular source file in file system.
    /// If source file is a directory then it attempts to search for an index.html.
    pub fn search(mut src: PathBuf) -> Result<StaticFileWithMeta, Box<dyn error::Error>> {
        trace!("Opening {}", src.display());
    pub fn search<P: AsRef<Path>>(src: P) -> Result<StaticFileWithMeta, Box<dyn error::Error>>
    where
        PathBuf: From<P>,
    {
        let mut src: PathBuf = src.into();
        trace!("Opening path {}", src.display());

        let mut auto_index = false;
        let meta = std::fs::metadata(&src)?;