Skip to content

Commit e6e677f

Browse files
areyiaandrewhavck
authored andcommitted
tests: handle h2 reset timing after partial response body
Allow the h2 proxy test to pass whether the response body DATA frame is observed before the downstream stream reset or the stream reset arrives first. Both orderings are valid for this error path, and newer h2 behavior can surface RST_STREAM(CANCEL) before the buffered body chunk is delivered. Also keep the h2 drain-loop cleanup explicit by using clearer expect messages and releasing flow-control capacity while draining the response.
1 parent 95de0f7 commit e6e677f

2 files changed

Lines changed: 31 additions & 6 deletions

File tree

pingora-core/src/protocols/http/v2/server.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,17 @@ mod test {
994994
assert_eq!(data, server_body);
995995

996996
req_body.send_data("".into(), true).unwrap(); // set EOS after read the resp body
997+
998+
// Drain the response to EOS before dropping the stream. Newer h2
999+
// sends RST_STREAM(CANCEL) when a still-open recv stream is dropped,
1000+
// which would race with the server reading the request EOS and turn
1001+
// the server-side read into a stream-reset error.
1002+
while let Some(chunk) = body.data().await {
1003+
let chunk = chunk.expect("response body error");
1004+
body.flow_control()
1005+
.release_capacity(chunk.len())
1006+
.expect("release capacity");
1007+
}
9971008
}));
9981009

9991010
let mut connection = handshake(Box::new(server), None).await.unwrap();
@@ -1024,8 +1035,12 @@ mod test {
10241035
http.write_body(server_body.into(), false).await.unwrap();
10251036
assert_eq!(http.body_bytes_sent(), 16);
10261037

1027-
// 3. Waiting for the client to close stream.
1038+
// 3. Read the empty DATA frame carrying the request EOS.
10281039
http.read_body_or_idle(http.is_body_done()).await.unwrap();
1040+
1041+
// 4. Finish the response so the client can drain it to EOS and
1042+
// close the stream cleanly instead of cancelling it.
1043+
http.finish().unwrap();
10291044
}));
10301045
}
10311046

pingora-proxy/tests/test_basic.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,11 +1108,21 @@ async fn test_error_after_headers_sent_rst_received() {
11081108
let response = response.await.unwrap();
11091109
let mut body = response.into_body();
11101110

1111-
let chunk = body.data().await.unwrap();
1112-
assert_eq!(chunk.unwrap(), Bytes::from_static(b"AAAAA"));
1113-
1114-
let err = body.data().await.unwrap().err().unwrap();
1115-
assert_eq!(err.reason().unwrap(), h2::Reason::CANCEL);
1111+
match body.data().await.expect("response body frame or reset") {
1112+
Ok(chunk) => {
1113+
assert_eq!(chunk, Bytes::from_static(b"AAAAA"));
1114+
1115+
let err = body
1116+
.data()
1117+
.await
1118+
.expect("response body reset")
1119+
.expect_err("expected stream reset");
1120+
assert_eq!(err.reason().expect("reset reason"), h2::Reason::CANCEL);
1121+
}
1122+
Err(err) => {
1123+
assert_eq!(err.reason().expect("reset reason"), h2::Reason::CANCEL);
1124+
}
1125+
}
11161126
}
11171127

11181128
#[tokio::test]

0 commit comments

Comments
 (0)