docserver/src/defs/req_headermap.rs

192 lines
6.1 KiB
Rust

use std::{
net::IpAddr,
collections::HashMap,
};
use axum::http::{header::FORWARDED, HeaderMap};
use forwarded_header_value::{ForwardedHeaderValue, Identifier};
use crate::defs::{
Config,
AppConnectInfo,
AUTHORIZATION,
REFERER,
BEARER,
USER_AGENT,
ACCEPT_LANGUAGE,
X_FORWARDED_FOR,
X_REAL_IP,
X_INTERNAL,
};
pub struct ReqHeaderMap {
pub header: HeaderMap,
pub req_path: Vec<String>,
pub app_connect_info: AppConnectInfo,
}
impl ReqHeaderMap {
pub fn new(header: HeaderMap, request_path: &str, app_connect_info: &AppConnectInfo) -> Self {
let req_path =
Self::req_end_path(request_path)
.split(",").map(|s| s.to_string())
.collect();
ReqHeaderMap {
header,
req_path,
app_connect_info: app_connect_info.to_owned(),
}
}
pub fn req_end_path(req_path: &str) -> String {
let arr_req_path: Vec<String> = req_path.split("/").map(|s| s.to_string()).collect();
format!("{}",arr_req_path[arr_req_path.len()-1])
}
pub fn auth(&self) -> String {
if let Some(auth) = self.header.get(AUTHORIZATION) {
format!("{}",auth.to_str().unwrap_or("").replace(&format!("{} ", BEARER),""))
} else {
String::from("")
}
}
pub fn referer(&self) -> String {
if let Some(referer) = self.header.get(REFERER) {
format!("{}",referer.to_str().unwrap_or(""))
} else {
String::from("")
}
}
pub fn internal(&self) -> String {
if let Some(internal) = self.header.get(X_INTERNAL) {
format!("{}",internal.to_str().unwrap_or(""))
} else {
String::from("")
}
}
pub fn is_browser(&self) -> bool {
if let Some(user_agent) = self.header.get(USER_AGENT) {
let agent = user_agent.to_str().unwrap_or("");
if agent.contains("Mozilla") {
true
} else if agent.contains("WebKit") {
true
} else if agent.contains("Chrome") {
true
} else {
false
}
} else {
false
}
}
#[allow(dead_code)]
pub fn is_curl(&self) -> bool {
if let Some(user_agent) = self.header.get(USER_AGENT) {
let agent = user_agent.to_str().unwrap_or("");
if agent.contains("curl") {
true
} else {
false
}
} else {
false
}
}
pub fn is_wget(&self) -> bool {
if let Some(user_agent) = self.header.get(USER_AGENT) {
let agent = user_agent.to_str().unwrap_or("").to_lowercase();
if agent.contains("wget") {
true
} else {
false
}
} else {
false
}
}
#[allow(dead_code)]
pub fn response_user_agent_html(&self) -> bool {
if let Some(user_agent) = self.header.get(USER_AGENT) {
let agent = user_agent.to_str().unwrap_or("").to_lowercase();
agent.contains("curl") || agent.contains("wget")
} else {
false
}
}
pub fn agent(&self) -> String {
if let Some(user_agent) = self.header.get(USER_AGENT) {
user_agent.to_str().unwrap_or("").to_owned()
} else {
String::from("")
}
}
pub fn lang(&self, config: &Config) -> String {
if let Some(langs) = self.header.get(ACCEPT_LANGUAGE) {
let langs_data = langs.to_str().unwrap_or("");
if langs_data.is_empty() {
format!("{}",config.dflt_lang)
} else {
let arr_langs: Vec<String> = langs_data.split(",").map(|s| s.to_string()).collect();
let arr_lang: Vec<String> = arr_langs[0].split("-").map(|s| s.to_string()).collect();
format!("{}",arr_lang[0])
}
} else {
format!("{}",config.dflt_lang)
}
}
/// Tries to parse the `x-real-ip` header
fn maybe_x_forwarded_for(&self) -> Option<IpAddr> {
self.header
.get(X_FORWARDED_FOR)
.and_then(|hv| hv.to_str().ok())
.and_then(|s| s.split(',').find_map(|s| s.trim().parse::<IpAddr>().ok()))
}
/// Tries to parse the `x-real-ip` header
fn maybe_x_real_ip(&self) -> Option<IpAddr> {
self.header
.get(X_REAL_IP)
.and_then(|hv| hv.to_str().ok())
.and_then(|s| s.parse::<IpAddr>().ok())
}
/// Tries to parse `forwarded` headers
fn maybe_forwarded(&self) -> Option<IpAddr> {
self.header
.get_all(FORWARDED).iter().find_map(|hv| {
hv.to_str()
.ok()
.and_then(|s| ForwardedHeaderValue::from_forwarded(s).ok())
.and_then(|f| {
f.iter()
.filter_map(|fs| fs.forwarded_for.as_ref())
.find_map(|ff| match ff {
Identifier::SocketAddr(a) => Some(a.ip()),
Identifier::IpAddr(ip) => Some(*ip),
_ => None,
})
})
})
}
pub fn ip(&self) -> String {
if let Some(ip) = self.maybe_x_real_ip()
.or_else(||self.maybe_x_forwarded_for())
.or_else(|| self.maybe_forwarded())
.or_else(|| None )
{
format!("{}",ip)
} else {
format!("{}", self.app_connect_info.remote_addr)
}
}
pub fn req_info(&self) -> HashMap<String,String> {
let mut req_data: HashMap<String,String> = HashMap::new();
req_data.insert(String::from("agent"), self.agent());
req_data.insert(String::from("ip"), self.ip());
req_data.insert(String::from("auth"), self.auth());
req_data.insert(String::from("ref"), self.referer());
req_data.insert(String::from("int"), self.internal());
req_data
}
}