This commit is contained in:
Robin Appelman 2020-12-03 16:28:19 +01:00
commit 58b51a72cf
4 changed files with 65 additions and 5 deletions

13
Cargo.lock generated
View file

@ -983,6 +983,18 @@ dependencies = [
"mio", "mio",
"pin-project-lite 0.1.11", "pin-project-lite 0.1.11",
"slab", "slab",
"tokio-macros",
]
[[package]]
name = "tokio-macros"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
dependencies = [
"proc-macro2",
"quote",
"syn",
] ]
[[package]] [[package]]
@ -1194,6 +1206,7 @@ dependencies = [
name = "warp-real-ip" name = "warp-real-ip"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"tokio",
"warp", "warp",
] ]

View file

@ -7,4 +7,7 @@ keywords = ["warp"]
categories = ["web-programming::http-server"] categories = ["web-programming::http-server"]
[dependencies] [dependencies]
warp = { version = "0.2" } warp = { version = "0.2" }
[dev-dependencies]
tokio = { version = "0.2", features = ["macros"] }

View file

@ -4,10 +4,13 @@ use warp::filters::addr::remote;
use warp::Filter; use warp::Filter;
/// Creates a `Filter` that provides the "real ip" of the connected client. /// Creates a `Filter` that provides the "real ip" of the connected client.
pub fn real_ip<'a>( ///
trusted_proxies: &'a [IpAddr], /// This uses the "x-forwarded-for" or "x-real-ip" headers set by reverse proxies.
) -> impl Filter<Extract = (Option<IpAddr>,), Error = Infallible> + Clone + 'a { /// To stop clients from abusing these headers, only headers set by trusted remotes will be accepted.
let forwarded_for = warp::header::<IpAddr>("X-FORWARDED-FOR") pub fn real_ip(
trusted_proxies: Vec<IpAddr>,
) -> impl Filter<Extract = (Option<IpAddr>,), Error = Infallible> + Clone {
let forwarded_for = warp::header::<IpAddr>("x-forwarded-for")
.or(warp::header("x-real-ip")) .or(warp::header("x-real-ip"))
.unify() .unify()
.map(Some) .map(Some)

41
tests/tests.rs Normal file
View file

@ -0,0 +1,41 @@
use std::net::IpAddr;
use warp::Filter;
use warp_real_ip::real_ip;
fn serve<'a>(trusted: Vec<IpAddr>) -> impl Filter<Extract = (String,)> + 'a {
warp::any()
.and(real_ip(trusted))
.map(|addr: Option<IpAddr>| addr.unwrap().to_string())
}
#[tokio::test]
async fn test_not_forwarded() {
let remote: IpAddr = [1, 2, 3, 4].into();
let res = warp::test::request()
.remote_addr((remote, 80).into())
.reply(&serve(vec![]))
.await;
assert_eq!(res.body(), "1.2.3.4");
}
#[tokio::test]
async fn test_not_trusted() {
let remote: IpAddr = [1, 2, 3, 4].into();
let res = warp::test::request()
.remote_addr((remote, 80).into())
.header("x-forwarded-for", "10.10.10.10")
.reply(&serve(vec![]))
.await;
assert_eq!(res.body(), "1.2.3.4");
}
#[tokio::test]
async fn test_trusted() {
let remote: IpAddr = [1, 2, 3, 4].into();
let res = warp::test::request()
.remote_addr((remote, 80).into())
.header("x-forwarded-for", "10.10.10.10")
.reply(&serve(vec![remote]))
.await;
assert_eq!(res.body(), "10.10.10.10");
}