trafficserver icon indicating copy to clipboard operation
trafficserver copied to clipboard

HTTP/2: Wait END_STREAM flag on half-closed(local) stream state

Open masaori335 opened this issue 7 months ago • 3 comments

Recently, we found that some clients send HEADERS frame followed by an empty DATA frame with the END_STREAM flag even for GET requests.

  • HEADERS frame with END_HEADERS flag
  • zero-length DATA frame with END_STREAM flag

Sometimes ATS closes the stream immediately after it sends DATA frame to the client, right after handling the HEADERS frame. In this case, ATS treats the zero-length DATA frame as a stream error because the stream is already closed.

However, this appears to be a bug. The spec[*1] says that an endpoint should keep the stream in the half-closed (local) state after sending END_STREAM flag and wait to receive END_STREAM flag from the peer before closing it.

With this change, ATS waits for the END_STREAM flag until the http.transaction_no_activity_timeout_in expires.

[*1] https://datatracker.ietf.org/doc/html/rfc9113#name-stream-states

masaori335 avatar May 27 '25 07:05 masaori335

The spec[*1] says that an endpoint should keep the stream in the half-closed (local) state after sending END_STREAM flag and wait to receive END_STREAM flag from the peer before closing it.

That's not true. Server can actively close the stream without waiting for END_STREAM if the server knows that receiving the rest of request is unnecessary. https://datatracker.ietf.org/doc/html/rfc9113#section-8.1-11

There is a way to close unnecessary streams cleanly. https://datatracker.ietf.org/doc/html/rfc9113#section-5.1-7.14.5 https://datatracker.ietf.org/doc/html/rfc9113#section-5.1-7.14.6

We should not retain resources to be used unnecessarily.

maskit avatar May 27 '25 17:05 maskit

All right, we can close the stream by sending a RST_STREAM. It might be better for resource usage point of view.

masaori335 avatar May 28 '25 07:05 masaori335

It doesn't seem like the fundamental issue is fixed.

I have transaction_active_timeout_in: 1 and sending a POST request that continues over 1 second causes stream errors with error code STREAM_CLOSED.

maskit avatar Jun 03 '25 01:06 maskit

Cherry-picked to 10.1.x branch

cmcfarlen avatar Jun 30 '25 15:06 cmcfarlen