fix: update Content-Length header when MITM modifies request body
The MITM modifier kept original HTTP headers (including Content-Length) when replacing the body. When injecting a ~200KB image into a ~66KB request, Google would only read Content-Length bytes, then hang waiting for a new request that never comes. Now we regex-replace the Content-Length header value to match the actual rechunked body size after modification.
This commit is contained in:
@@ -578,9 +578,13 @@ async fn handle_http_over_tls(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(modified_body) = super::modify::modify_request(&raw_body, tool_ctx.as_ref()) {
|
if let Some(modified_body) = super::modify::modify_request(&raw_body, tool_ctx.as_ref()) {
|
||||||
// Rebuild request_buf: original headers + rechunked modified body
|
// Rebuild request_buf: headers (with updated Content-Length) + rechunked modified body
|
||||||
let new_chunked = super::modify::rechunk(&modified_body);
|
let new_chunked = super::modify::rechunk(&modified_body);
|
||||||
let mut new_buf = request_buf[..headers_end].to_vec();
|
|
||||||
|
// Fix Content-Length header to match new body size
|
||||||
|
let header_str = String::from_utf8_lossy(&request_buf[..headers_end]);
|
||||||
|
let updated_headers = update_content_length(&header_str, new_chunked.len());
|
||||||
|
let mut new_buf = updated_headers.into_bytes();
|
||||||
new_buf.extend_from_slice(&new_chunked);
|
new_buf.extend_from_slice(&new_chunked);
|
||||||
request_buf = new_buf;
|
request_buf = new_buf;
|
||||||
}
|
}
|
||||||
@@ -1030,3 +1034,15 @@ fn parse_http_request_meta(buf: &[u8]) -> (usize, usize, bool) {
|
|||||||
(headers_end, content_length, is_streaming)
|
(headers_end, content_length, is_streaming)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rewrite the Content-Length header in raw HTTP headers to match a new body size.
|
||||||
|
/// If no Content-Length header is found, returns the headers unchanged.
|
||||||
|
fn update_content_length(headers: &str, new_body_len: usize) -> String {
|
||||||
|
use regex::Regex;
|
||||||
|
let re = Regex::new(r"(?im)^content-length:\s*\d+").unwrap();
|
||||||
|
if re.is_match(headers) {
|
||||||
|
re.replace(headers, format!("Content-Length: {new_body_len}"))
|
||||||
|
.to_string()
|
||||||
|
} else {
|
||||||
|
headers.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user