use barehttp::config::Config;
use barehttp::{Error, HttpClient, Response};
use std::io::{Read, Write};
use std::net::TcpListener;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
#[test]
fn buffered_parse_huge_cl_does_not_allocate_body() {
let msg = b"HTTP/1.1 200 OK\r\nContent-Length: 999999999999999\r\n\r\n";
assert!(Response::parse(msg).is_err());
}
#[test]
fn connection_rejects_cl_over_max_before_body_read() {
let listener = TcpListener::bind("127.0.0.1:0").expect("bind");
let addr = listener.local_addr().expect("addr");
let seen = Arc::new(Mutex::new(Vec::new()));
let seen2 = Arc::clone(&seen);
thread::spawn(move || {
if let Ok((mut stream, _)) = listener.accept() {
let _ = stream.set_read_timeout(Some(Duration::from_secs(2)));
let mut buf = [0u8; 2048];
let mut got = Vec::new();
loop {
match stream.read(&mut buf) {
Ok(0) => break,
Ok(n) => {
got.extend_from_slice(&buf[..n]);
if got.windows(4).any(|w| w == b"\r\n\r\n") {
break;
}
},
Err(_) => break,
}
}
*seen2.lock().unwrap() = got;
let resp = b"HTTP/1.1 200 OK\r\nContent-Length: 104857600\r\nConnection: close\r\n\r\n";
let _ = stream.write_all(resp);
}
});
let client = HttpClient::with_config(
Config::builder()
.max_redirects(0)
.max_idle_per_host(0)
.max_response_body_size(1024)
.timeout_connect(Some(Duration::from_secs(2)))
.timeout_read(Some(Duration::from_secs(2)))
.timeout_write(Some(Duration::from_secs(2)))
.build(),
);
let url = format!("http://{addr}/");
let err = client.get(&url).call().expect_err("must fail body limit");
assert!(
matches!(err, Error::BodyExceedsLimit(1024)),
"expected BodyExceedsLimit before allocating 100MiB, got {err:?}"
);
}