|
|
|
@ -94,7 +94,10 @@ |
|
|
|
|
//! }
|
|
|
|
|
//! }
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
#![cfg_attr(all(not(stable), test), feature(test))] |
|
|
|
|
|
|
|
|
|
#[cfg(all(not(stable), test))] |
|
|
|
|
extern crate test; |
|
|
|
|
|
|
|
|
|
use hyper::client::{connect::dns::GaiResolver, HttpConnector}; |
|
|
|
|
use hyper::header::{HeaderMap, HeaderValue, HeaderName, HOST}; |
|
|
|
@ -253,3 +256,201 @@ pub async fn call( |
|
|
|
|
let proxied_response = create_proxied_response(response); |
|
|
|
|
Ok(proxied_response) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(all(not(stable), test))] |
|
|
|
|
mod tests { |
|
|
|
|
use rand::distributions::Alphanumeric; |
|
|
|
|
use rand::prelude::*; |
|
|
|
|
use hyper::header::HeaderName; |
|
|
|
|
use hyper::Uri; |
|
|
|
|
use hyper::{HeaderMap, Request, Response}; |
|
|
|
|
use std::net::Ipv4Addr; |
|
|
|
|
use std::str::FromStr; |
|
|
|
|
use test::Bencher; |
|
|
|
|
use test_context::AsyncTestContext; |
|
|
|
|
use tokiotest_httpserver::HttpTestContext; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn generate_string() -> String { |
|
|
|
|
let take = rand::thread_rng().gen::<u8>().into(); |
|
|
|
|
rand::thread_rng() |
|
|
|
|
.sample_iter(&Alphanumeric) |
|
|
|
|
.take(take) |
|
|
|
|
.map(char::from) |
|
|
|
|
.collect() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn build_headers() -> HeaderMap { |
|
|
|
|
let mut headers_map: HeaderMap = (&*super::HOP_HEADERS) |
|
|
|
|
.iter() |
|
|
|
|
.map(|el: &'static HeaderName| (el.clone(), generate_string().parse().unwrap())) |
|
|
|
|
.collect(); |
|
|
|
|
|
|
|
|
|
for _i in 0..20 { |
|
|
|
|
'inserted: loop { |
|
|
|
|
if let Ok(value) = |
|
|
|
|
hyper::header::HeaderName::from_str(&generate_string().to_lowercase()) |
|
|
|
|
{ |
|
|
|
|
headers_map.insert(value, generate_string().parse().unwrap()); |
|
|
|
|
|
|
|
|
|
break 'inserted; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
headers_map |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[bench] |
|
|
|
|
fn proxy_call(b: &mut Bencher) { |
|
|
|
|
use tokio::runtime::Runtime; |
|
|
|
|
let rt = Runtime::new().unwrap(); |
|
|
|
|
|
|
|
|
|
let uri = Uri::from_static("http://0.0.0.0:8080/me?hello=world"); |
|
|
|
|
|
|
|
|
|
let http_context: HttpTestContext = rt.block_on(async { AsyncTestContext::setup().await }); |
|
|
|
|
|
|
|
|
|
let forward_url = &format!("http://0.0.0.0:{}", http_context.port); |
|
|
|
|
|
|
|
|
|
let headers_map = build_headers(); |
|
|
|
|
|
|
|
|
|
let client_ip = std::net::IpAddr::from(Ipv4Addr::from_str("0.0.0.0").unwrap()); |
|
|
|
|
|
|
|
|
|
b.iter(|| { |
|
|
|
|
rt.block_on(async { |
|
|
|
|
let mut request = Request::builder().uri(uri.clone()); |
|
|
|
|
|
|
|
|
|
*request.headers_mut().unwrap() = headers_map.clone(); |
|
|
|
|
|
|
|
|
|
super::call( |
|
|
|
|
client_ip, |
|
|
|
|
forward_url, |
|
|
|
|
request.body(hyper::Body::from("")).unwrap(), |
|
|
|
|
) |
|
|
|
|
.await |
|
|
|
|
.unwrap(); |
|
|
|
|
}) |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[bench] |
|
|
|
|
fn create_proxied_response(b: &mut Bencher) { |
|
|
|
|
let headers_map = build_headers(); |
|
|
|
|
|
|
|
|
|
b.iter(|| { |
|
|
|
|
let mut response = Response::builder().status(200); |
|
|
|
|
|
|
|
|
|
*response.headers_mut().unwrap() = headers_map.clone(); |
|
|
|
|
|
|
|
|
|
super::create_proxied_response(response.body(()).unwrap(), hyper::header::HeaderValue::from_static("me")); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[bench] |
|
|
|
|
fn forward_url_with_str_ending_slash(b: &mut Bencher) { |
|
|
|
|
let uri = Uri::from_static("http://0.0.0.0:8080/me"); |
|
|
|
|
let port = rand::thread_rng().gen::<u8>(); |
|
|
|
|
let forward_url = &format!("http://0.0.0.0:{}/", port); |
|
|
|
|
|
|
|
|
|
b.iter(|| { |
|
|
|
|
let request = Request::builder().uri(uri.clone()).body(()); |
|
|
|
|
|
|
|
|
|
super::forward_uri(forward_url, &request.unwrap()); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[bench] |
|
|
|
|
fn forward_url_with_str_ending_slash_and_query(b: &mut Bencher) { |
|
|
|
|
let uri = Uri::from_static("http://0.0.0.0:8080/me?hello=world"); |
|
|
|
|
let port = rand::thread_rng().gen::<u8>(); |
|
|
|
|
let forward_url = &format!("http://0.0.0.0:{}/", port); |
|
|
|
|
|
|
|
|
|
b.iter(|| { |
|
|
|
|
let request = Request::builder().uri(uri.clone()).body(()); |
|
|
|
|
|
|
|
|
|
super::forward_uri(forward_url, &request.unwrap()); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[bench] |
|
|
|
|
fn forward_url_no_ending_slash(b: &mut Bencher) { |
|
|
|
|
let uri = Uri::from_static("http://0.0.0.0:8080/me"); |
|
|
|
|
let port = rand::thread_rng().gen::<u8>(); |
|
|
|
|
let forward_url = &format!("http://0.0.0.0:{}", port); |
|
|
|
|
|
|
|
|
|
b.iter(|| { |
|
|
|
|
let request = Request::builder().uri(uri.clone()).body(()); |
|
|
|
|
|
|
|
|
|
super::forward_uri(forward_url, &request.unwrap()); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[bench] |
|
|
|
|
fn forward_url_with_query(b: &mut Bencher) { |
|
|
|
|
let uri = Uri::from_static("http://0.0.0.0:8080/me?hello=world"); |
|
|
|
|
let port = rand::thread_rng().gen::<u8>(); |
|
|
|
|
let forward_url = &format!("http://0.0.0.0:{}", port); |
|
|
|
|
|
|
|
|
|
b.iter(|| { |
|
|
|
|
let request = Request::builder().uri(uri.clone()).body(()); |
|
|
|
|
|
|
|
|
|
super::forward_uri(forward_url, &request.unwrap()); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[bench] |
|
|
|
|
fn create_proxied_request_forwarded_for_occupied(b: &mut Bencher) { |
|
|
|
|
let uri = Uri::from_static("http://0.0.0.0:8080/me?hello=world"); |
|
|
|
|
let port = rand::thread_rng().gen::<u8>(); |
|
|
|
|
let forward_url = &format!("http://0.0.0.0:{}", port); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut headers_map = build_headers(); |
|
|
|
|
|
|
|
|
|
headers_map.insert( |
|
|
|
|
HeaderName::from_static("x-forwarded-for"), |
|
|
|
|
"0.0.0.0".parse().unwrap(), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
let client_ip = std::net::IpAddr::from(Ipv4Addr::from_str("0.0.0.0").unwrap()); |
|
|
|
|
|
|
|
|
|
b.iter(|| { |
|
|
|
|
let mut request = Request::builder().uri(uri.clone()); |
|
|
|
|
|
|
|
|
|
*request.headers_mut().unwrap() = headers_map.clone(); |
|
|
|
|
|
|
|
|
|
super::create_proxied_request( |
|
|
|
|
client_ip, |
|
|
|
|
forward_url, |
|
|
|
|
request.body(()).unwrap(), |
|
|
|
|
) |
|
|
|
|
.unwrap(); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[bench] |
|
|
|
|
fn create_proxied_request_forwarded_for_vacant(b: &mut Bencher) { |
|
|
|
|
let uri = Uri::from_static("http://0.0.0.0:8080/me?hello=world"); |
|
|
|
|
let port = rand::thread_rng().gen::<u8>(); |
|
|
|
|
let forward_url = &format!("http://0.0.0.0:{}", port); |
|
|
|
|
|
|
|
|
|
let headers_map = build_headers(); |
|
|
|
|
|
|
|
|
|
let client_ip = std::net::IpAddr::from(Ipv4Addr::from_str("0.0.0.0").unwrap()); |
|
|
|
|
|
|
|
|
|
b.iter(|| { |
|
|
|
|
let mut request = Request::builder().uri(uri.clone()); |
|
|
|
|
|
|
|
|
|
*request.headers_mut().unwrap() = headers_map.clone(); |
|
|
|
|
|
|
|
|
|
super::create_proxied_request( |
|
|
|
|
client_ip, |
|
|
|
|
forward_url, |
|
|
|
|
request.body(()).unwrap(), |
|
|
|
|
) |
|
|
|
|
.unwrap(); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|