use crate::common::Address;
use hyper::{
header::{GetAll, HeaderValue},
http::uri::Authority,
HeaderMap, Uri, Version,
};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
pub fn authority_addr(scheme_str: Option<&str>, authority: &Authority) -> Option<Address> {
let port = match authority.port_u16() {
Some(port) => port,
None => {
match scheme_str {
None => 80, Some("http") => 80,
Some("https") => 443,
_ => return None, }
}
};
let host_str = authority.host();
if host_str.starts_with('[') && host_str.ends_with(']') {
let addr = &host_str[1..host_str.len() - 1];
match addr.parse::<Ipv6Addr>() {
Ok(a) => Some(Address::from(SocketAddr::new(IpAddr::V6(a), port))),
Err(..) => None,
}
} else {
match host_str.parse::<Ipv4Addr>() {
Ok(a) => Some(Address::from(SocketAddr::new(IpAddr::V4(a), port))),
Err(..) => Some(Address::DomainNameAddress(host_str.to_owned(), port)),
}
}
}
pub fn host_addr(uri: &Uri) -> Option<Address> {
match uri.authority() {
None => None,
Some(authority) => authority_addr(uri.scheme_str(), authority),
}
}
fn get_keep_alive_val(values: GetAll<HeaderValue>) -> Option<bool> {
let mut conn_keep_alive = None;
for value in values {
if let Ok(value) = value.to_str() {
if value.eq_ignore_ascii_case("close") {
conn_keep_alive = Some(false);
} else {
for part in value.split(',') {
let part = part.trim();
if part.eq_ignore_ascii_case("keep-alive") {
conn_keep_alive = Some(true);
break;
}
}
}
}
}
conn_keep_alive
}
pub fn check_keep_alive(
version: Version,
headers: &HeaderMap<HeaderValue>,
check_proxy: bool,
) -> bool {
let mut conn_keep_alive = !matches!(version, Version::HTTP_09 | Version::HTTP_10);
if check_proxy {
if let Some(b) = get_keep_alive_val(headers.get_all("Proxy-Connection")) {
conn_keep_alive = b
}
}
if let Some(b) = get_keep_alive_val(headers.get_all("Connection")) {
conn_keep_alive = b
}
conn_keep_alive
}