mod common;
use std::time::{Duration, Instant};
use common::*;
use noxy::http::HttpService;
use noxy::middleware::SlidingWindow;
use tower::Layer;
#[tokio::test]
async fn sliding_window_blocks_excess_requests() {
let upstream_addr = start_upstream("hello").await;
let proxy_addr = start_proxy(vec![Box::new(|inner: HttpService| {
let layer = SlidingWindow::global(2, Duration::from_millis(500));
tower::util::BoxService::new(layer.layer(inner))
})])
.await;
let client = http_client(proxy_addr);
let url = format!("https://localhost:{}/", upstream_addr.port());
let start = Instant::now();
for i in 0..3 {
let resp = client.get(&url).send().await.unwrap();
assert_eq!(
resp.text().await.unwrap(),
"hello",
"request {i} should succeed"
);
}
let elapsed = start.elapsed();
assert!(
elapsed >= Duration::from_millis(400),
"3 requests with sliding window of 2/500ms should take ~500ms, took {elapsed:?}"
);
}
#[tokio::test]
async fn sliding_window_per_host_isolates_hosts() {
let upstream_addr = start_http_upstream("hello").await;
let window = SlidingWindow::per_host(1, Duration::from_secs(1));
let proxy_addr = start_reverse_proxy(
&format!("http://{upstream_addr}"),
vec![Box::new(move |inner: HttpService| {
tower::util::BoxService::new(window.layer(inner))
})],
)
.await;
let client = reqwest::Client::new();
let url = format!("http://{proxy_addr}/");
let resp = client
.get(&url)
.header("host", "host-a")
.send()
.await
.unwrap();
assert_eq!(resp.status(), 200);
let start = std::time::Instant::now();
let resp = client
.get(&url)
.header("host", "host-a")
.send()
.await
.unwrap();
let host_a_elapsed = start.elapsed();
assert_eq!(resp.status(), 200);
let start = std::time::Instant::now();
let resp = client
.get(&url)
.header("host", "host-b")
.send()
.await
.unwrap();
let host_b_elapsed = start.elapsed();
assert_eq!(resp.status(), 200);
assert!(
host_a_elapsed >= Duration::from_millis(800),
"host-a second request should be delayed ~1s, took {host_a_elapsed:?}"
);
assert!(
host_b_elapsed < Duration::from_millis(500),
"host-b should not be affected, took {host_b_elapsed:?}"
);
}