Implement IP header extraction
This commit is contained in:
parent
8e5387600a
commit
ac17b66a8d
5 changed files with 67 additions and 1 deletions
|
@ -24,4 +24,5 @@ headers = "0.3.5"
|
||||||
url = {version = "2.2.2", features = ["serde"]}
|
url = {version = "2.2.2", features = ["serde"]}
|
||||||
askama = "0.10"
|
askama = "0.10"
|
||||||
urlencoding = "2.1.0"
|
urlencoding = "2.1.0"
|
||||||
thiserror = "1.0.30"
|
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 config;
|
||||||
mod error;
|
mod error;
|
||||||
mod ipfs;
|
mod ipfs;
|
||||||
|
mod lib;
|
||||||
mod v1;
|
mod v1;
|
||||||
|
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
|
|
Loading…
Reference in a new issue