diff --git a/ballerina-tests/http2-tests/tests/http2_configuration_request_limit_config_test.bal b/ballerina-tests/http2-tests/tests/http2_configuration_request_limit_config_test.bal index 83924c0dd3..92fe98ebed 100644 --- a/ballerina-tests/http2-tests/tests/http2_configuration_request_limit_config_test.bal +++ b/ballerina-tests/http2-tests/tests/http2_configuration_request_limit_config_test.bal @@ -145,28 +145,33 @@ function testHttp2ValidHeaderLength() returns error? { } //Tests the behaviour when header size is greater than the configured threshold -// TODO: Enable after fixing this issue : https://github.com/ballerina-platform/ballerina-standard-library/issues/3963 -@test:Config { - enable: false -} +@test:Config {} function testHttp2InvalidHeaderLength() returns error? { http:Client limitClient = check new ("http://localhost:" + http2RequestLimitsTestPort3.toString(), http2Settings = {http2PriorKnowledge: true}); - http:Response response = check limitClient->get("/lowRequestHeaderLimit/invalidHeaderSize", {"X-Test": getLargeHeader()}); + http:Response|http:Error response = limitClient->get("/lowRequestHeaderLimit/invalidHeaderSize", {"X-Test": getLargeHeader()}); //431 Request Header Fields Too Large - test:assertEquals(response.statusCode, 431, msg = "Found unexpected output"); + if response is http:Error { + test:assertTrue(response is http:ClientError); + test:assertEquals(response.message(), "Header size exceeded max allowed size (600)"); + } else { + test:assertEquals(response.statusCode, 431, msg = "Found unexpected output"); + } } // Tests the fallback behaviour when header size is greater than the configured http2 service // TODO: Enable after fixing this issue : https://github.com/ballerina-platform/ballerina-standard-library/issues/3963 -@test:Config { - enable: false -} +@test:Config {} function testHttp2Http2ServiceInvalidHeaderLength() returns error? { http:Client limitClient = check new ("http://localhost:" + requestLimitsTestPort5.toString(), http2Settings = {http2PriorKnowledge: true}); - http:Response response = check limitClient->get("/http2service/invalidHeaderSize", {"X-Test": getLargeHeader()}); - test:assertEquals(response.statusCode, 431, msg = "Found unexpected output"); + http:Response|http:Error response = limitClient->get("/http2service/invalidHeaderSize", {"X-Test": getLargeHeader()}); + if response is http:Error { + test:assertTrue(response is http:ClientError); + test:assertEquals(response.message(), "Header size exceeded max allowed size (850)"); + } else { + test:assertEquals(response.statusCode, 431, msg = "Found unexpected output"); + } } //Tests the behaviour when payload size is greater than the configured threshold diff --git a/changelog.md b/changelog.md index 4e430bf06d..27f41de3df 100644 --- a/changelog.md +++ b/changelog.md @@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Fixed - [Remove unused import from Http2StateUtil](https://github.com/ballerina-platform/ballerina-library/issues/5966) - [Fix client getting hanged when server closes connection in the ALPN handshake](https://github.com/ballerina-platform/ballerina-library/issues/6003) +- [Fix client getting hanged when multiple requests are sent which exceed `maxHeaderSize`](https://github.com/ballerina-platform/ballerina-library/issues/6000) ## [2.10.5] - 2023-12-06 diff --git a/native/src/main/java/io/ballerina/stdlib/http/transport/contractimpl/common/states/Http2StateUtil.java b/native/src/main/java/io/ballerina/stdlib/http/transport/contractimpl/common/states/Http2StateUtil.java index e8ed1daf54..e72fd6ae8a 100644 --- a/native/src/main/java/io/ballerina/stdlib/http/transport/contractimpl/common/states/Http2StateUtil.java +++ b/native/src/main/java/io/ballerina/stdlib/http/transport/contractimpl/common/states/Http2StateUtil.java @@ -43,6 +43,7 @@ import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; import io.netty.handler.codec.http.DefaultLastHttpContent; import io.netty.handler.codec.http.HttpContent; import io.netty.handler.codec.http.HttpHeaderNames; @@ -320,9 +321,13 @@ public static void writeHttp2Headers(ChannelHandlerContext ctx, OutboundMsgHolde return; } } - - encoder.writeHeaders(ctx, streamId, http2Headers, dependencyId, weight, false, 0, endStream, - ctx.newPromise()); + ChannelPromise promise = ctx.newPromise(); + encoder.writeHeaders(ctx, streamId, http2Headers, dependencyId, weight, false, 0, endStream, promise); + promise.addListener((ChannelFutureListener) channelFuture -> { + if (!channelFuture.isSuccess()) { + outboundMsgHolder.getResponseFuture().notifyHttpListener(channelFuture.cause()); + } + }); encoder.flowController().writePendingBytes(); ctx.flush();