index : static-web-server.git

ascending towards madness

author Jose Quintana <joseluisquintana20@gmail.com> 2020-04-18 0:10:01.0 +00:00:00
committer Jose Quintana <joseluisquintana20@gmail.com> 2020-04-18 0:10:01.0 +00:00:00
commit
e40016dfdadfdd8204360efee04ef64eaadf68dc [patch]
tree
81c7bc742f041fffe7203709b34a4dd4f3e9fcbf
parent
2e2a6ac6f7941c450ba56d754a9e214a0c07f508
download
e40016dfdadfdd8204360efee04ef64eaadf68dc.tar.gz

chore: directory paths checking



Diff

 src/helpers.rs     | 26 ++++++++++++++++++++++++++
 src/main.rs        |  1 +
 src/staticfiles.rs | 49 +++++++++++++++++++++++++++++++++++++++----------
 3 files changed, 66 insertions(+), 10 deletions(-)

diff --git a/src/helpers.rs b/src/helpers.rs
new file mode 100644
index 0000000..535f8fd
--- /dev/null
+++ b/src/helpers.rs
@@ -0,0 +1,26 @@
use std::path::{Path, PathBuf};

pub enum PathError {
    PathNotFound,
    NotDirectory,
}

/// Validate a path if exist and is a directory.
pub fn validate_dirpath<P: AsRef<Path>>(path: P) -> Result<PathBuf, PathError>
where
    PathBuf: From<P>,
{
    match PathBuf::from(path) {
        p if !p.exists() => Result::Err(PathError::PathNotFound),
        p if !p.is_dir() => Result::Err(PathError::NotDirectory),
        p => Result::Ok(p),
    }
}

/// Format a `PathError` description
pub fn path_error_fmt(err: PathError, dirname: &str, dirpath: &str) -> String {
    match err {
        PathError::PathNotFound => format!("{} path \"{}\" was not found", dirname, dirpath),
        PathError::NotDirectory => format!("{} path \"{}\" is not a directory", dirname, dirpath),
    }
}
diff --git a/src/main.rs b/src/main.rs
index 3166c66..ec5f806 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,6 +10,7 @@ use structopt::StructOpt;
mod config;
mod error_page;
mod gzip;
mod helpers;
mod logger;
mod signal_manager;
mod staticfiles;
diff --git a/src/staticfiles.rs b/src/staticfiles.rs
index cd152f1..056af6e 100644
--- a/src/staticfiles.rs
+++ b/src/staticfiles.rs
@@ -1,5 +1,6 @@
use crate::error_page::ErrorPage;
use crate::gzip::GzipMiddleware;
use crate::helpers;
use crate::logger::Logger;

use iron::prelude::*;
@@ -26,10 +27,41 @@ impl StaticFiles {

    /// Handle static files for current `StaticFiles` middleware.
    pub fn handle(&self) -> Chain {
        let mut chain = Chain::new(
            Staticfile::new(self.opts.root_dir.as_str())
                .expect("Directory to serve files was not found"),
        );
        // Check the root directory
        let root_dir = match helpers::validate_dirpath(&self.opts.root_dir) {
            Err(err) => {
                error!(
                    "{}",
                    helpers::path_error_fmt(err, "root", &self.opts.root_dir)
                );
                std::process::exit(1);
            }
            Ok(val) => val,
        };

        // Check the assets directory
        let assets_dir = match helpers::validate_dirpath(&self.opts.assets_dir) {
            Err(err) => {
                error!(
                    "{}",
                    helpers::path_error_fmt(err, "assets", &self.opts.assets_dir)
                );
                std::process::exit(1);
            }
            Ok(val) => val,
        };

        let assets_dirname = match assets_dir.iter().last() {
            Some(val) => val.to_str().unwrap().to_string(),
            None => {
                error!("assets directory name was not determined");
                std::process::exit(1);
            }
        };

        // Define middleware chain
        let mut chain =
            Chain::new(Staticfile::new(&root_dir).expect("Directory to serve files was not found"));
        let one_day = Duration::new(60 * 60 * 24, 0);
        let one_year = Duration::new(60 * 60 * 24 * 365, 0);
        let default_content_type = "text/html"
@@ -37,16 +69,13 @@ impl StaticFiles {
            .expect("Unable to create a default content type header");

        chain.link_after(ModifyWith::new(Cache::new(one_day)));
        chain.link_after(Prefix::new(
            &[self.opts.assets_dir.as_str()],
            Cache::new(one_year),
        ));
        chain.link_after(Prefix::new(&[assets_dirname], Cache::new(one_year)));
        chain.link_after(GuessContentType::new(default_content_type));
        chain.link_after(GzipMiddleware);
        chain.link_after(Logger);
        chain.link_after(ErrorPage::new(
            self.opts.page_404_path.as_str(),
            self.opts.page_50x_path.as_str(),
            &self.opts.page_404_path,
            &self.opts.page_50x_path,
        ));
        chain
    }