use rocket::{
async_trait,
request::{FromRequest, Outcome, Request},
};
use std::{convert::Infallible, fmt::Display, net::IpAddr, str::FromStr};
#[derive(Debug, Clone)]
pub struct ClientIP(IpAddr);
impl Display for ClientIP {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[async_trait]
impl<'r> FromRequest<'r> for ClientIP {
type Error = Infallible;
async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
if let Some(ip) = req.headers().get_one("CF-Connecting-IP") {
Outcome::Success(ClientIP(IpAddr::from_str(ip).unwrap()))
} else {
Outcome::Success(ClientIP(
req.client_ip()
.unwrap_or_else(|| IpAddr::from_str("127.0.0.1").unwrap()),
))
}
}
}