fix(tests): read complete requests in the snapshot conflict server
This commit is contained in:
@@ -238,8 +238,7 @@ fn spawn_conflict_server() -> Result<(String, TestServer), Box<dyn Error>> {
|
|||||||
.to_string();
|
.to_string();
|
||||||
let server = thread::spawn(move || -> std::io::Result<()> {
|
let server = thread::spawn(move || -> std::io::Result<()> {
|
||||||
let (mut stream, _) = listener.accept()?;
|
let (mut stream, _) = listener.accept()?;
|
||||||
let mut request = [0_u8; 16 * 1024];
|
read_complete_request(&mut stream)?;
|
||||||
let _ = stream.read(&mut request)?;
|
|
||||||
let response = format!(
|
let response = format!(
|
||||||
"HTTP/1.1 409 Conflict\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{body}",
|
"HTTP/1.1 409 Conflict\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{body}",
|
||||||
body.len()
|
body.len()
|
||||||
@@ -250,6 +249,39 @@ fn spawn_conflict_server() -> Result<(String, TestServer), Box<dyn Error>> {
|
|||||||
Ok((format!("http://{address}"), server))
|
Ok((format!("http://{address}"), server))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reads headers plus the full `Content-Length` body. Responding before the
|
||||||
|
/// client finishes writing resets the connection and makes tests flaky.
|
||||||
|
fn read_complete_request(stream: &mut std::net::TcpStream) -> std::io::Result<Vec<u8>> {
|
||||||
|
let mut request = Vec::new();
|
||||||
|
let mut chunk = [0_u8; 1024];
|
||||||
|
let header_end = loop {
|
||||||
|
if let Some(position) = request.windows(4).position(|window| window == b"\r\n\r\n") {
|
||||||
|
break position + 4;
|
||||||
|
}
|
||||||
|
let read = stream.read(&mut chunk)?;
|
||||||
|
if read == 0 || request.len() + read > 64 * 1024 {
|
||||||
|
return Err(std::io::Error::other("request headers are incomplete"));
|
||||||
|
}
|
||||||
|
request.extend_from_slice(&chunk[..read]);
|
||||||
|
};
|
||||||
|
let headers = String::from_utf8_lossy(&request[..header_end]);
|
||||||
|
let content_length = headers
|
||||||
|
.split("\r\n")
|
||||||
|
.find_map(|line| {
|
||||||
|
let (name, value) = line.split_once(':')?;
|
||||||
|
name.eq_ignore_ascii_case("content-length").then(|| value.trim().parse().ok())?
|
||||||
|
})
|
||||||
|
.unwrap_or(0_usize);
|
||||||
|
while request.len() < header_end + content_length {
|
||||||
|
let read = stream.read(&mut chunk)?;
|
||||||
|
if read == 0 {
|
||||||
|
return Err(std::io::Error::other("request body is incomplete"));
|
||||||
|
}
|
||||||
|
request.extend_from_slice(&chunk[..read]);
|
||||||
|
}
|
||||||
|
Ok(request)
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_logout_server(
|
fn spawn_logout_server(
|
||||||
status_line: &'static str,
|
status_line: &'static str,
|
||||||
body: &str,
|
body: &str,
|
||||||
|
|||||||
Reference in New Issue
Block a user