Implement IP header extraction
This commit is contained in:
parent
8e5387600a
commit
ac17b66a8d
5 changed files with 67 additions and 1 deletions
|
@ -25,3 +25,4 @@ url = {version = "2.2.2", features = ["serde"]}
|
|||
askama = "0.10"
|
||||
urlencoding = "2.1.0"
|
||||
thiserror = "1.0.30"
|
||||
async-trait = "0.1.51"
|
28
src/lib/error.rs
Normal file
28
src/lib/error.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use std::{convert::Infallible, net::AddrParseError};
|
||||
|
||||
use axum::{
|
||||
body::{Bytes, Full},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use hyper::{header::ToStrError, StatusCode};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ExtractError {
|
||||
#[error("`{0}` header is missing")]
|
||||
HeaderMissing(String),
|
||||
#[error("Header value contains illegal character: {0}")]
|
||||
ToStr(#[from] ToStrError),
|
||||
#[error("Header value is not a valid IP address: {0}")]
|
||||
IPParse(#[from] AddrParseError),
|
||||
}
|
||||
|
||||
impl IntoResponse for ExtractError {
|
||||
type Body = Full<Bytes>;
|
||||
|
||||
type BodyError = Infallible;
|
||||
|
||||
fn into_response(self) -> hyper::Response<Self::Body> {
|
||||
(StatusCode::BAD_REQUEST, self.to_string()).into_response()
|
||||
}
|
||||
}
|
32
src/lib/ipheader.rs
Normal file
32
src/lib/ipheader.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use std::{net::IpAddr, str::FromStr};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use axum::extract::{FromRequest, RequestParts};
|
||||
|
||||
use super::error::ExtractError;
|
||||
|
||||
pub struct ExtractIP(pub IpAddr);
|
||||
|
||||
#[async_trait]
|
||||
impl<B> FromRequest<B> for ExtractIP
|
||||
where
|
||||
B: Send,
|
||||
{
|
||||
type Rejection = ExtractError;
|
||||
|
||||
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
let header = req
|
||||
.headers()
|
||||
.and_then(|headers| headers.get("x-forwarded-for"));
|
||||
let header = header.ok_or(ExtractError::HeaderMissing("X-Forwarded-For".to_string()))?;
|
||||
let mut value = header.to_str()?;
|
||||
let pos = value.chars().position(|r| r == ',');
|
||||
value = match pos {
|
||||
Some(p) => &value[0..p],
|
||||
None => value,
|
||||
};
|
||||
let ip = IpAddr::from_str(value)?;
|
||||
|
||||
Ok(Self(ip))
|
||||
}
|
||||
}
|
4
src/lib/mod.rs
Normal file
4
src/lib/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
mod error;
|
||||
mod ipheader;
|
||||
|
||||
pub use ipheader::ExtractIP;
|
|
@ -14,6 +14,7 @@ mod cdn;
|
|||
mod config;
|
||||
mod error;
|
||||
mod ipfs;
|
||||
mod lib;
|
||||
mod v1;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
|
|
Loading…
Reference in a new issue