use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};
use std::fs;
use std::path::Path;
use std::fmt::Write;
use crate::headers::cd::DispositionType;
const DEFAULT_SERVE_DIR: &'static str = ".";
pub trait FileServeConfig: std::marker::Send {
fn max_buffer_size() -> u64 {
65_536
}
fn content_disposition_map(typ: mime::Name) -> DispositionType {
match typ {
mime::IMAGE | mime::TEXT | mime::VIDEO => DispositionType::Inline,
_ => DispositionType::Attachment,
}
}
fn is_use_etag(_path: &Path) -> bool {
true
}
fn is_use_last_modifier(_path: &Path) -> bool {
true
}
}
pub trait DirectoryListingConfig {
fn create_body(_base: &Path, path: &Path, dir: fs::ReadDir) -> String {
let mut body = String::with_capacity(150);
let _ = write!(body, "<html>\n");
let _ = write!(body, " <head>\n");
let _ = write!(body, " <title>Index of {}</title>\n", path.display());
let _ = write!(body, " </head>\n");
let _ = write!(body, " <body>\n");
let _ = write!(body, " <h1>Index of {}</h1>\n", path.display());
let _ = write!(body, " <ul>\n");
for entry in dir.filter_map(|entry| entry.ok()) {
if entry.file_name().to_str().map(|entry| entry.starts_with(".")).unwrap_or(false) {
continue;
}
let is_dir = match entry.metadata().map(|meta| meta.file_type()) {
Ok(meta) => if !meta.is_dir() && !meta.is_file() && !meta.is_symlink() {
continue;
} else {
meta.is_dir()
},
Err(_) => continue,
};
let _ = write!(body, "<li><a href=\"{}\">{}",
utf8_percent_encode(&entry.path().to_string_lossy(), DEFAULT_ENCODE_SET),
v_htmlescape::escape(&entry.file_name().to_string_lossy()));
if is_dir {
let _ = write!(body, "/");
}
let _ = write!(body, "</a></li>\n");
}
let _ = write!(body, " </ul>\n");
let _ = write!(body, " </body>\n");
let _ = write!(body, "</html>\n");
body
}
}
pub trait StaticFileConfig {
type FileService: FileServeConfig + 'static;
type DirService: DirectoryListingConfig;
fn is_method_allowed(method: &http::Method) -> bool {
match method {
&http::Method::GET | &http::Method::HEAD => true,
_ => false,
}
}
fn serve_dir(&self) -> &Path {
Path::new(DEFAULT_SERVE_DIR)
}
fn index_file(&self, _path: &Path) -> Option<&Path> {
None
}
fn handle_directory(&self, _path: &Path) -> bool {
false
}
fn thread_pool_builder(builder: &mut tokio_threadpool::Builder) -> &mut tokio_threadpool::Builder {
builder.name_prefix("http-fs")
}
}
pub struct DefaultConfig;
impl FileServeConfig for DefaultConfig {}
impl DirectoryListingConfig for DefaultConfig {}
impl StaticFileConfig for DefaultConfig {
type FileService = Self;
type DirService = Self;
}