Skip to content

Commit

Permalink
Use RST_STREAM(NO_ERROR) in case server early respond (#633) (#634)
Browse files Browse the repository at this point in the history
Http2 Server are allowed to early respond without fully
  consuming client input stream, but must respond with an
  error code of NO_ERROR when sending RST_STREAM.
  Nginx treat any other error code as fatal if not done so

  Commit change error code from CANCEL to NO_ERROR, when the
  server is early responding to the client

  #633
  https://trac.nginx.org/nginx/ticket/2376
  • Loading branch information
erebe committed Aug 15, 2022
1 parent 756384f commit b0f54d8
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
14 changes: 13 additions & 1 deletion src/proto/streams/streams.rs
Expand Up @@ -1461,9 +1461,21 @@ fn drop_stream_ref(inner: &Mutex<Inner>, key: store::Key) {

fn maybe_cancel(stream: &mut store::Ptr, actions: &mut Actions, counts: &mut Counts) {
if stream.is_canceled_interest() {
// Server is allowed to early respond without fully consuming the client input stream
// But per the RFC, must send a RST_STREAM(NO_ERROR) in such cases. https://www.rfc-editor.org/rfc/rfc7540#section-8.1
// Some other http2 implementation may interpret other error code as fatal if not respected (i.e: nginx https://trac.nginx.org/nginx/ticket/2376)
let reason = if counts.peer().is_server()
&& stream.state.is_send_closed()
&& stream.state.is_recv_streaming()
{
Reason::NO_ERROR
} else {
Reason::CANCEL
};

actions
.send
.schedule_implicit_reset(stream, Reason::CANCEL, counts, &mut actions.task);
.schedule_implicit_reset(stream, reason, counts, &mut actions.task);
actions.recv.enqueue_reset_expiration(stream, counts);
}
}
Expand Down
4 changes: 3 additions & 1 deletion tests/h2-tests/tests/server.rs
Expand Up @@ -566,7 +566,9 @@ async fn sends_reset_cancel_when_req_body_is_dropped() {
client
.recv_frame(frames::headers(1).response(200).eos())
.await;
client.recv_frame(frames::reset(1).cancel()).await;
client
.recv_frame(frames::reset(1).reason(Reason::NO_ERROR))
.await;
};

let srv = async move {
Expand Down

0 comments on commit b0f54d8

Please sign in to comment.