extern crate walkdir;
use std::collections::HashMap;
use std::path::{Path, Component};
use std::ffi::OsStr;
use self::walkdir::WalkDir;
use utils::file::is_hidden;
#[derive(Clone)]
pub struct Router {
pub static_routes: HashMap<String, String>,
}
impl Router {
pub fn new() -> Router {
let static_routes = HashMap::new();
Router {
static_routes
}
}
pub fn from(folder: &str) -> Router {
let mut router = Router::new();
router.register_static_routes(folder);
router
}
pub fn register_static_routes(&mut self, folder: &str) {
vprintln!("Registering routes for: {}", &folder);
let directory = Path::new(&folder);
let folder = directory.file_name().map_or("", |f| f.to_str().unwrap());
for entry in WalkDir::new(&directory).into_iter()
.filter_entry(|e| !is_hidden(e) ) {
let entry = match entry {
Ok(e) => e,
_ => continue,
};
let is_file = entry.metadata().ok().map_or(false, |m| m.is_file());
if is_file {
let url = Router::create_url(entry.path(), folder);
let abs_path = entry.path();
self.static_routes.insert(url,
abs_path.to_str().unwrap().to_string());
}
}
vprintln!("Routes: {:?}", self.static_routes);
}
fn create_url(path: &Path, dir: &str) -> String {
let components = path.components();
let filtered: Vec<&str> = components
.skip_while(|c| Some(*c) != Some(Component::Normal(OsStr::new(dir))))
.map(|c| c.as_os_str())
.filter_map(|c| c.to_str())
.collect();
let result = filtered.join("/");
if result.starts_with('/') {
result
} else {
format!("/{}", result)
}
}
pub fn is_static_content(&self, path: &str) -> bool {
self.static_routes.contains_key(path)
}
pub fn get(&self, path: &str) -> &str {
&self.static_routes[path]
}
}
#[cfg(test)]
mod tests {
extern crate tempdir;
use super::*;
use std::fs::File;
use self::tempdir::TempDir;
#[test]
fn test_register_static_routes() {
let test_dir = TempDir::new("rhs-tests").unwrap();
let filepath = test_dir.path().join("test.txt");
let _ = File::create(filepath).unwrap();
let mut router = Router::new();
assert_eq!(0, router.static_routes.len());
router.register_static_routes(test_dir.path().to_str().unwrap());
assert_eq!(1, router.static_routes.len());
}
#[test]
fn test_route_checking() {
let test_dir = TempDir::new("rhs-tests").unwrap();
let path_str = test_dir.path().file_name().unwrap().to_str().unwrap();
let filepath = test_dir.path().join("test.txt");
let _ = File::create(filepath).unwrap();
let router = Router::from(test_dir.path().to_str().unwrap());
println!("path prefix in route: {}", path_str);
println!("routes: {:?}", router.static_routes);
assert!(router.is_static_content(&format!("/{}/test.txt", path_str)));
assert!(!router.is_static_content(&format!("/{}/this_does_not_exist.txt", path_str)));
}
#[test]
fn test_preserve_directory_structure() {
let test_dir = TempDir::new("rhs-tests")
.expect("Could not create test dir");
let test_dir_name = test_dir.path().file_name().unwrap().to_str().unwrap();
let path = test_dir.path();
let sub_dir = TempDir::new_in(&test_dir, "foo")
.expect("Could not create sub dir");
let sub_dir_name = sub_dir.path().file_name().unwrap().to_str().unwrap();
let file_name = sub_dir.path().join("test.txt");
println!("{:?}", file_name);
let _ = File::create(file_name.as_path()).unwrap();
let router = Router::from(path.to_str().unwrap());
println!("routes: {:?}", router.static_routes);
assert!(
router
.is_static_content(
&format!("/{test_dir}/{sub_dir}/test.txt",
test_dir=test_dir_name,
sub_dir=sub_dir_name)));
}
}