pub mod bytes;
pub mod http_request;
pub mod http_response;
pub mod http_stream;
pub mod zero_copy;
use std::collections::HashMap;
pub trait GetHeaderChild {
fn get_header_child(&self) -> HashMap<&str, &str>;
}
impl GetHeaderChild for &str {
fn get_header_child(&self) -> HashMap<&str, &str> {
let mut headers = HashMap::new();
for part in self.split(';') {
let part = part.trim();
if let Some(eq_pos) = part.find('=') {
let key = part[..eq_pos].trim();
let value = part[eq_pos + 1..]
.trim()
.trim_matches('"')
.trim_matches('\'');
headers.insert(key, value);
}
}
headers
}
}
pub trait StringUtil {
fn copy_string(&self) -> String;
}
impl StringUtil for String {
fn copy_string(&self) -> String {
self.clone()
}
}
pub use crate::helpers::traits::bytes::find_header_end as find_header_end_optimized;
use std::path::{Component, Path, PathBuf};
pub fn safe_path_join<R: AsRef<Path>, U: AsRef<Path>>(root: R, user_path: U) -> Option<PathBuf> {
let mut result = root.as_ref().to_path_buf();
for component in user_path.as_ref().components() {
match component {
Component::Normal(seg) => result.push(seg),
Component::CurDir => {} Component::ParentDir | Component::RootDir | Component::Prefix(_) => return None,
}
}
Some(result)
}
#[cfg(test)]
mod tests {
use super::safe_path_join;
use std::path::PathBuf;
#[test]
fn safe_path_join_appends_normal_segments() {
let got = safe_path_join("/srv/static", "css/app.css").unwrap();
assert_eq!(
got,
PathBuf::from("/srv/static").join("css").join("app.css")
);
}
#[test]
fn safe_path_join_rejects_parent_dir() {
assert!(safe_path_join("/srv/static", "../etc/passwd").is_none());
assert!(safe_path_join("/srv/static", "a/../../b").is_none());
assert!(safe_path_join("/srv/static", "a/b/..").is_none());
}
#[test]
fn safe_path_join_rejects_absolute_path() {
assert!(safe_path_join("/srv/static", "/etc/passwd").is_none());
}
#[test]
fn safe_path_join_allows_current_dir() {
let got = safe_path_join("/srv/static", "./index.html").unwrap();
assert_eq!(got, PathBuf::from("/srv/static").join("index.html"));
}
#[test]
fn safe_path_join_handles_empty_user_path() {
let got = safe_path_join("/srv/static", "").unwrap();
assert_eq!(got, PathBuf::from("/srv/static"));
}
#[cfg(windows)]
#[test]
fn safe_path_join_rejects_windows_prefix() {
assert!(safe_path_join("D:\\srv\\static", "C:\\Windows\\System32\\cmd.exe").is_none());
}
}