From 71cc8a9cd6419c2e5eff3584b623d3ca7eb6d52e Mon Sep 17 00:00:00 2001 From: Jose Quintana Date: Fri, 12 Feb 2021 01:36:46 +0100 Subject: [PATCH] feat: preliminary windows support refs #29 --- src/helpers.rs | 16 ++++++++++++++++ src/lib.rs | 3 +++ src/staticfile_middleware/staticfile.rs | 74 ++++++++++++++++++++++++++------------------------------------------------ src/staticfiles.rs | 28 +++++++++------------------- 4 files changed, 54 insertions(+), 67 deletions(-) diff --git a/src/helpers.rs b/src/helpers.rs index d251a0c..f8b1713 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -33,3 +33,19 @@ where ))), } } + +#[cfg(not(windows))] +pub fn adjust_canonicalization>(p: P) -> String { + p.as_ref().display().to_string() +} + +#[cfg(windows)] +pub fn adjust_canonicalization>(p: P) -> String { + const VERBATIM_PREFIX: &str = r#"\\?\"#; + let p = p.as_ref().display().to_string(); + if p.starts_with(VERBATIM_PREFIX) { + p[VERBATIM_PREFIX.len()..].to_string() + } else { + p + } +} diff --git a/src/lib.rs b/src/lib.rs index 4841d9b..b0eea07 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,10 @@ pub mod gzip; pub mod helpers; pub mod logger; pub mod server; + +#[cfg(not(windows))] pub mod signal_manager; + pub mod staticfile_middleware; pub mod staticfiles; diff --git a/src/staticfile_middleware/staticfile.rs b/src/staticfile_middleware/staticfile.rs index 06836c9..392e614 100644 --- a/src/staticfile_middleware/staticfile.rs +++ b/src/staticfile_middleware/staticfile.rs @@ -1,7 +1,7 @@ use humansize::{file_size_opts, FileSize}; use iron::headers::{ - AcceptEncoding, AcceptRanges, ContentEncoding, ContentLength, Encoding, HttpDate, - IfModifiedSince, LastModified, Range, RangeUnit, + AcceptRanges, ContentEncoding, ContentLength, Encoding, HttpDate, IfModifiedSince, + LastModified, Range, RangeUnit, }; use iron::method::Method; use iron::middleware::Handler; @@ -10,11 +10,11 @@ use iron::prelude::*; use iron::status; use std::fs::{File, Metadata}; use std::path::{Path, PathBuf}; +use std::time::SystemTime; use std::time::UNIX_EPOCH; use std::{error, io}; -use std::{ffi::OsString, time::SystemTime}; -use crate::staticfile_middleware::helpers; +use crate::helpers as utils; use crate::staticfile_middleware::partial_file::PartialFile; /// Recursively serves files from the specified root and assets directories. @@ -25,12 +25,12 @@ pub struct Staticfile { } impl Staticfile { - pub fn new

(root: P, assets: P, dir_list: bool) -> io::Result + pub fn new>(root: P, assets: P, dir_list: bool) -> io::Result where - P: AsRef, + PathBuf: From

, { - let root = root.as_ref().canonicalize()?; - let assets = assets.as_ref().canonicalize()?; + let root = root.into(); + let assets = assets.into(); Ok(Staticfile { root, @@ -64,12 +64,15 @@ impl Staticfile { res }; - let resolved = resolved.canonicalize()?; - let path = if is_assets { &self.assets } else { &self.root }; + let resolved = PathBuf::from(utils::adjust_canonicalization(resolved)); + let base_path = if is_assets { &self.assets } else { &self.root }; // Protect against path/directory traversal - if !resolved.starts_with(&path) { - return Result::Err(From::from(format!("Cannot leave {:?} path", &path))); + if !resolved.starts_with(&base_path) { + return Err(From::from(format!( + "Cannot leave {:?} base path", + &base_path + ))); } Ok(resolved) @@ -173,10 +176,12 @@ impl Handler for Staticfile { // 2. Otherwise proceed with the normal file-response process // Get current file metadata - let accept_gz = helpers::accept_gzip(req.headers.get::()); - let file = match StaticFileWithMetadata::search(&file_path, accept_gz) { + let file = match StaticFileWithMetadata::search(file_path.clone()) { Ok(f) => f, - Err(_) => return Ok(Response::with(status::NotFound)), + Err(e) => { + trace!("{}", e); + return Ok(Response::with(status::NotFound)); + } }; // Apply last modified date time @@ -260,47 +265,20 @@ struct StaticFileWithMetadata { } impl StaticFileWithMetadata { - pub fn search

( - path: P, - allow_gz: bool, - ) -> Result> - // TODO: unbox - where - P: Into, - { - let mut file_path = path.into(); + pub fn search(path: PathBuf) -> Result> { + let mut file_path = path; trace!("Opening {}", file_path.display()); - let mut file = StaticFileWithMetadata::open(&file_path)?; + let metadata = std::fs::metadata(&file_path)?; // Look for index.html inside of a directory - if file.metadata.is_dir() { + if metadata.is_dir() { file_path.push("index.html"); trace!("Redirecting to index {}", file_path.display()); - file = StaticFileWithMetadata::open(&file_path)?; } + let file = StaticFileWithMetadata::open(&file_path)?; if file.metadata.is_file() { - if allow_gz { - // Find the foo.gz sibling of foo - let mut side_by_side_path: OsString = file_path.into(); - side_by_side_path.push(".gz"); - file_path = side_by_side_path.into(); - trace!("Attempting to find side-by-side GZ {}", file_path.display()); - - match StaticFileWithMetadata::open(&file_path) { - Ok(mut gz_file) => { - if gz_file.metadata.is_file() { - gz_file.is_gz = true; - Ok(gz_file) - } else { - Ok(file) - } - } - Err(_) => Ok(file), - } - } else { - Ok(file) - } + Ok(file) } else { Err(From::from("Requested path was not a regular file")) } diff --git a/src/staticfiles.rs b/src/staticfiles.rs index 1794385..ac3ef2e 100644 --- a/src/staticfiles.rs +++ b/src/staticfiles.rs @@ -1,8 +1,8 @@ use iron::mime; use iron::prelude::*; use iron_cors::CorsMiddleware; -use std::collections::HashSet; use std::time::Duration; +use std::{collections::HashSet, path::PathBuf}; use crate::error_page::ErrorPage; use crate::gzip::GzipMiddleware; @@ -32,26 +32,16 @@ impl StaticFiles { /// Handle static files for current `StaticFiles` middleware. pub fn handle(&self) -> Chain { - // Check the root directory - let root_dir = &match helpers::get_valid_dirpath(&self.opts.root_dir) { - Err(e) => { - error!("{}", e); - std::process::exit(1) - } - Ok(v) => v, - }; + // Check root directory + let p = PathBuf::from(&self.opts.root_dir).canonicalize().unwrap(); + let root_dir = PathBuf::from(helpers::adjust_canonicalization(p)); - // Check the assets directory - let assets_dir = &match helpers::get_valid_dirpath(&self.opts.assets_dir) { - Err(e) => { - error!("{}", e); - std::process::exit(1) - } - Ok(v) => v, - }; + // Check assets directory + let p = PathBuf::from(&self.opts.assets_dir).canonicalize().unwrap(); + let assets_dir = PathBuf::from(helpers::adjust_canonicalization(p)); - // Get the assets directory name - let assets_dirname = &match helpers::get_dirname(assets_dir) { + // Get assets directory name + let assets_dirname = &match helpers::get_dirname(&assets_dir) { Err(e) => { error!("{}", e); std::process::exit(1) -- libgit2 1.7.2