From 54be7c0e2cf00d01962e4186f8952f5e5e7dc138 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Wed, 14 Oct 2020 23:07:05 -0300 Subject: [PATCH] add: entity tag support Implements an Entity Tag hash by obtaining the date created, the date of the last modification and the size of the file. --- CHANGELOG.md | 6 ++++++ src/config.rs | 2 -- src/handler/file_explorer/handler.rs | 11 +++++++++-- src/server/etag.rs | 17 +++++++++++++++++ src/server/mod.rs | 2 ++ 5 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/server/etag.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 5056567c..7f36bcc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changes +## v0.0.10 + +### Added + +* [Etag Support](https://github.com/EstebanBorai/http-server/commit/32dc9a2e6b32bb18906ef06d45c155731d91519e) + ## v0.0.9 ### Added diff --git a/src/config.rs b/src/config.rs index 63811990..d2e26630 100644 --- a/src/config.rs +++ b/src/config.rs @@ -28,8 +28,6 @@ impl From> for Config { }; let silent = matches.is_present(SILENT.1); - - // at this point the values provided to the config are validated by the CLI Self { address, port, diff --git a/src/handler/file_explorer/handler.rs b/src/handler/file_explorer/handler.rs index bedb0fb5..30e7543c 100644 --- a/src/handler/file_explorer/handler.rs +++ b/src/handler/file_explorer/handler.rs @@ -1,5 +1,6 @@ use crate::file_explorer::FileExplorer; use crate::handler::build_html; +use crate::server::make_entity_tag; use ascii::AsciiString; use std::fs::{read_dir, File}; use tiny_http::{Request, Response, ResponseBox}; @@ -16,10 +17,12 @@ pub fn file_explorer(request: Request, file_explorer: &FileExplorer) -> (Request Ok(entry) => { if entry.is_file { let mime_type = mime_guess::from_path(&entry.path) - .first_or_octet_stream() - .to_string(); + .first_or_octet_stream() + .to_string(); let mime_type = AsciiString::from_ascii(mime_type.as_bytes()).unwrap(); let file = File::open(entry.path).unwrap(); + let entity_tag = make_entity_tag(&file.metadata().unwrap()); + let entity_tag = AsciiString::from_ascii(entity_tag).unwrap(); ( request, @@ -28,6 +31,10 @@ pub fn file_explorer(request: Request, file_explorer: &FileExplorer) -> (Request field: "Content-Type".parse().unwrap(), value: mime_type, }) + .with_header(tiny_http::Header { + field: "Etag".parse().unwrap(), + value: entity_tag + }) .boxed(), ) } else { diff --git a/src/server/etag.rs b/src/server/etag.rs new file mode 100644 index 00000000..88abc545 --- /dev/null +++ b/src/server/etag.rs @@ -0,0 +1,17 @@ +use std::fs::Metadata; +use std::time::SystemTime; +use std::hash::{Hash, Hasher}; +use std::collections::hash_map::DefaultHasher; + +/// Creates an Entity Tag from a `File` `Metadata` +pub fn make_entity_tag(meta: &Metadata) -> String { + let mut created_hasher = DefaultHasher::new(); + let mut modified_hasher = DefaultHasher::new(); + let mut size_hasher = DefaultHasher::new(); + + meta.len().hash(&mut size_hasher); + meta.created().unwrap_or(SystemTime::now()).hash(&mut created_hasher); + meta.modified().unwrap_or(SystemTime::now()).hash(&mut modified_hasher); + + format!("{0:x}{1:x}{2:x}", created_hasher.finish(), modified_hasher.finish(), size_hasher.finish()) +} diff --git a/src/server/mod.rs b/src/server/mod.rs index 8e815309..61a62336 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,3 +1,5 @@ +mod etag; mod http; +pub use etag::*; pub use http::*;