You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
1.7 KiB

//! Contains info about the requester
use super::*;
use std::net::{
SocketAddr,
};
use std::{fmt,error};
use forwarded_list::XForwardedFor;
#[derive(Debug)]
pub struct Requester
{
source: Option<SocketAddr>,
x_forwarded_for: XForwardedFor,
}
pub use std::net::IpAddr;
impl Requester
{
pub fn new(source: Option<SocketAddr>, x_forwarded_for: XForwardedFor) -> Result<Self, NoIpError>
{
if source.is_none() && x_forwarded_for.addrs().len() == 0 {
Err(NoIpError)
} else {
Ok(Self{
source,
x_forwarded_for,
})
}
}
}
/// Rejection error when the client's IP could not be determined.
#[derive(Debug)]
pub struct NoIpError;
impl warp::reject::Reject for NoIpError{}
impl error::Error for NoIpError{}
impl fmt::Display for NoIpError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "no remote host IP address could be found")
}
}
/// Extract the IP using the specified settings for trusting the `X-Forwarded-For` header.
///
/// # Returns
/// A filter to perform the extraction
#[inline] pub fn extract(trust_x: bool) -> impl Fn(Option<SocketAddr>, XForwardedFor) -> Result<ClientInfo,NoIpError> + Clone
{
move |opt, x| {
if trust_x {
x.into_first().ok_or(NoIpError)
} else {
opt.map(|x| x.ip()).ok_or(NoIpError)
}.map(|ip_addr|
// Create ClientInfo
ClientInfo {
ip_addr
})
}
}
/// Information about the client
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ClientInfo
{
pub ip_addr: IpAddr
}
impl fmt::Display for ClientInfo
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "ip: {}", self.ip_addr)
}
}