use axum::extract::{ConnectInfo, FromRequestParts};
use axum::http::request::Parts;
use axum_client_ip::RightmostXForwardedFor;
use std::convert::Infallible;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tracing::warn;
#[derive(Debug, Clone, Copy)]
pub struct ClientIpAddr(pub IpAddr);
impl<S> FromRequestParts<S> for ClientIpAddr
where
S: Send + Sync,
{
type Rejection = Infallible;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
if let Ok(RightmostXForwardedFor(ip)) =
RightmostXForwardedFor::from_request_parts(parts, state).await
{
return Ok(ClientIpAddr(ip));
}
if let Ok(ConnectInfo(addr)) =
ConnectInfo::<SocketAddr>::from_request_parts(parts, state).await
{
return Ok(ClientIpAddr(addr.ip()));
}
warn!("ClientIpAddr: no X-Forwarded-For or ConnectInfo found; using 0.0.0.0 fallback");
Ok(ClientIpAddr(IpAddr::V4(Ipv4Addr::UNSPECIFIED)))
}
}