@@ -447,6 +447,69 @@ TEST_P(ConnectTerminationIntegrationTest, IgnoreH11HostField) {
447447 sendRawHttpAndWaitForResponse (lookupPort (" http" ), full_request.c_str (), &response, true ););
448448}
449449
450+ TEST_P (ConnectTerminationIntegrationTest, EarlyConnectDataRejectedWithOverride) {
451+ config_helper_.addRuntimeOverride (" envoy.reloadable_features.reject_early_connect_data" , " true" );
452+ initialize ();
453+
454+ codec_client_ = makeHttpConnection (lookupPort (" http" ));
455+ // Send CONNECT request and immediately send some data without waiting for 200
456+ // response from Envoy.
457+ auto encoder_decoder = codec_client_->startRequest (connect_headers_);
458+ request_encoder_ = &encoder_decoder.first ;
459+ codec_client_->sendData (*request_encoder_, " premature data" , false );
460+ response_ = std::move (encoder_decoder.second );
461+
462+ // Envoy will try top open upstream connection before the premature CONNECT data is detected.
463+ ASSERT_TRUE (fake_upstreams_[0 ]->waitForRawConnection (fake_raw_upstream_connection_));
464+
465+ response_->waitForHeaders ();
466+ EXPECT_EQ (response_->headers ().getStatusValue (), " 400" );
467+ EXPECT_TRUE (response_->waitForEndStream ());
468+
469+ // Because the downstream connection is closed by Envoy without sending any data the
470+ // upstream connection will remain in the pool and will not be closed.
471+ // However it should not have any data in it.
472+ EXPECT_FALSE (fake_raw_upstream_connection_->hasData ());
473+ cleanupUpstreamAndDownstream ();
474+ }
475+
476+ TEST_P (ConnectTerminationIntegrationTest, EarlyConnectDataAllowedByDefault) {
477+ initialize ();
478+
479+ codec_client_ = makeHttpConnection (lookupPort (" http" ));
480+ // Send CONNECT request and immediately send some data without waiting for 200
481+ // response from Envoy.
482+ auto encoder_decoder = codec_client_->startRequest (connect_headers_);
483+ request_encoder_ = &encoder_decoder.first ;
484+ codec_client_->sendData (*request_encoder_, " premature data" , false );
485+ response_ = std::move (encoder_decoder.second );
486+
487+ // Wait for the data to arrive upstream.
488+ ASSERT_TRUE (fake_upstreams_[0 ]->waitForRawConnection (fake_raw_upstream_connection_));
489+ ASSERT_TRUE (fake_raw_upstream_connection_->waitForData (
490+ FakeRawConnection::waitForInexactMatch (" premature data" )));
491+
492+ // Send some data downstream.
493+ ASSERT_TRUE (fake_raw_upstream_connection_->write (" upstream_send_data" ));
494+
495+ // Wait for the headers and data to arrive downstream.
496+ response_->waitForHeaders ();
497+ response_->waitForBodyData (strlen (" upstream_send_data" ));
498+ EXPECT_EQ (" upstream_send_data" , response_->body ());
499+
500+ codec_client_->sendData (*request_encoder_, " " , true );
501+ ASSERT_TRUE (fake_raw_upstream_connection_->waitForHalfClose ());
502+
503+ ASSERT_TRUE (fake_raw_upstream_connection_->close ());
504+ if (downstream_protocol_ == Http::CodecType::HTTP1) {
505+ ASSERT_TRUE (codec_client_->waitForDisconnect ());
506+ } else {
507+ ASSERT_TRUE (response_->waitForEndStream ());
508+ ASSERT_FALSE (response_->reset ());
509+ }
510+ cleanupUpstreamAndDownstream ();
511+ }
512+
450513INSTANTIATE_TEST_SUITE_P (HttpAndIpVersions, ConnectTerminationIntegrationTest,
451514 testing::ValuesIn (HttpProtocolIntegrationTest::getProtocolTestParams(
452515 {Http::CodecType::HTTP1, Http::CodecType::HTTP2,
0 commit comments