eba4fd1
use std::net::{IpAddr, SocketAddr};
use axum::http::HeaderMap;
use ipnet::IpNet;
pub fn resolve_client_ip(
peer: Option<SocketAddr>,
headers: &HeaderMap,
trusted_proxies: &[IpNet],
) -> Option<IpAddr> {
match peer {
Some(addr) if in_nets(addr.ip(), trusted_proxies) => forwarded_ip(headers),
Some(addr) => Some(addr.ip()),
None => None,
}
}
pub fn in_nets(ip: IpAddr, nets: &[IpNet]) -> bool {
nets.iter().any(|net| net.contains(&ip))
}
fn forwarded_ip(headers: &HeaderMap) -> Option<IpAddr> {
if let Some(value) = headers
.get("x-forwarded-for")
.and_then(|value| value.to_str().ok())
&& let Some(first) = value
.split(',')
.map(str::trim)
.find(|item| !item.is_empty())
&& let Ok(ip) = first.parse::<IpAddr>()
{
return Some(ip);
}
if let Some(value) = headers
.get("x-real-ip")
.and_then(|value| value.to_str().ok())
&& let Ok(ip) = value.trim().parse::<IpAddr>()
{
return Some(ip);
}
None
}