diff --git a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2StreamHandling.scala b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2StreamHandling.scala index 2969be8a7..26decba61 100644 --- a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2StreamHandling.scala +++ b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/http2/Http2StreamHandling.scala @@ -445,6 +445,11 @@ private[http2] trait Http2StreamHandling extends GraphStageLogic with LogHelper case _: WindowUpdateFrame => // We're not planning on sending any data on this stream anymore, so we don't care about window updates. this + case rst: RstStreamFrame => + val headers = ParsedHeadersFrame(rst.streamId, endStream = false, Seq((":status", "429")), None) + dispatchSubstream(headers, Right(Source.failed(new PeerClosedStreamException(rst.streamId, rst.errorCode))), + correlationAttributes) + Closed case _ => expectIncomingStream(event, Closed, HalfClosedLocal(_), correlationAttributes) } diff --git a/http2-tests/src/test/scala/org/apache/pekko/http/impl/engine/http2/Http2ClientSpec.scala b/http2-tests/src/test/scala/org/apache/pekko/http/impl/engine/http2/Http2ClientSpec.scala index 6220625a0..97b665724 100644 --- a/http2-tests/src/test/scala/org/apache/pekko/http/impl/engine/http2/Http2ClientSpec.scala +++ b/http2-tests/src/test/scala/org/apache/pekko/http/impl/engine/http2/Http2ClientSpec.scala @@ -291,6 +291,24 @@ class Http2ClientSpec extends PekkoSpecWithMaterializer(""" val dynamicTableUpdateTo8192 = ByteString(63, 225, 63) headerPayload.take(3) shouldBe dynamicTableUpdateTo8192 }) + "close stream if peer sends RST_STREAM frame with REFUSED_STREAM".inAssertAllStagesStopped( + new TestSetup with NetProbes { + val data = ByteString("abcd") + user.emitRequest(Post("/", HttpEntity(data))) + val TheStreamId = network.expect[HeadersFrame]().streamId + network.expectDATA(TheStreamId, endStream = true, data) + + network.sendRST_STREAM(TheStreamId, ErrorCode.REFUSED_STREAM) + + val response = user.expectResponse() + response.status should be(StatusCodes.TooManyRequests) + + val entityDataIn = ByteStringSinkProbe(response.entity.dataBytes) + val error = entityDataIn.expectError() + error.getMessage shouldBe "Stream with ID [1] was closed by peer with code REFUSED_STREAM(0x07)" + + connectionShouldStillBeUsable() + }) } "support stream for response data" should {