diff --git a/src/core/ext/filters/client_channel/xds/xds_api.cc b/src/core/ext/filters/client_channel/xds/xds_api.cc index 69490b776fd..d4c2f380f50 100644 --- a/src/core/ext/filters/client_channel/xds/xds_api.cc +++ b/src/core/ext/filters/client_channel/xds/xds_api.cc @@ -1081,6 +1081,13 @@ grpc_error* RouteConfigParse( const envoy_api_v2_route_Route* route = routes[i]; const envoy_api_v2_route_RouteMatch* match = envoy_api_v2_route_Route_match(route); + const google_protobuf_BoolValue* case_sensitive = + envoy_api_v2_route_RouteMatch_case_sensitive(match); + if (case_sensitive != nullptr && + !google_protobuf_BoolValue_value(case_sensitive)) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "case_sensitive if set must be set to true."); + } XdsApi::RdsUpdate::RdsRoute rds_route; if (envoy_api_v2_route_RouteMatch_has_prefix(match)) { upb_strview prefix = envoy_api_v2_route_RouteMatch_prefix(match); diff --git a/src/proto/grpc/testing/xds/lds_rds_for_test.proto b/src/proto/grpc/testing/xds/lds_rds_for_test.proto index ec2a46b7c88..a4d48b28d1a 100644 --- a/src/proto/grpc/testing/xds/lds_rds_for_test.proto +++ b/src/proto/grpc/testing/xds/lds_rds_for_test.proto @@ -29,6 +29,10 @@ import "google/protobuf/any.proto"; import "google/protobuf/wrappers.proto"; import "src/proto/grpc/testing/xds/cds_for_test.proto"; +message BoolValue { + // The bool value. + bool value = 1; +} message RouteMatch { oneof path_specifier { @@ -37,6 +41,7 @@ message RouteMatch { string prefix = 1; string path = 2; } + BoolValue case_sensitive = 4; } message WeightedCluster { diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index a163c49c24a..688d6cfd987 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -2004,6 +2004,26 @@ TEST_P(XdsResolverOnlyTest, DefaultRouteSpecifiesSlashPrefix) { WaitForAllBackends(); } +TEST_P(XdsResolverOnlyTest, DefaultRouteCaseInsensitive) { + RouteConfiguration route_config = + balancers_[0]->ads_service()->default_route_config(); + route_config.mutable_virtual_hosts(0) + ->mutable_routes(0) + ->mutable_match() + ->mutable_case_sensitive() + ->set_value(false); + balancers_[0]->ads_service()->SetLdsResource( + AdsServiceImpl::BuildListener(route_config)); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", GetBackendPorts()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + AdsServiceImpl::BuildEdsResource(args)); + CheckRpcSendOk(5, RpcOptions().set_wait_for_ready(true)); +} + class XdsResolverLoadReportingOnlyTest : public XdsEnd2endTest { public: XdsResolverLoadReportingOnlyTest() : XdsEnd2endTest(4, 1, 3) {} @@ -2390,6 +2410,29 @@ TEST_P(LdsRdsTest, RouteMatchHasUnsupportedSpecifier) { "No prefix field found in Default RouteMatch."); } +// Tests that LDS client should send a NACK if route match has a case_sensitive +// set to false. +TEST_P(LdsRdsTest, RouteMatchHasCaseSensitiveFalse) { + gpr_setenv("GRPC_XDS_EXPERIMENTAL_ROUTING", "true"); + RouteConfiguration route_config = + balancers_[0]->ads_service()->default_route_config(); + auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); + route1->mutable_match()->set_prefix("/grpc.testing.EchoTest1Service/"); + route1->mutable_match()->mutable_case_sensitive()->set_value(false); + auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes(); + default_route->mutable_match()->set_prefix(""); + default_route->mutable_route()->set_cluster(kDefaultResourceName); + SetRouteConfiguration(0, route_config); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + CheckRpcSendFailure(); + const auto& response_state = RouteConfigurationResponseState(0); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_EQ(response_state.error_message, + "case_sensitive if set must be set to true."); + gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ROUTING"); +} + // Tests that LDS client should send a NACK if route match has a prefix // string with no "/". TEST_P(LdsRdsTest, RouteMatchHasInvalidPrefixNonEmptyNoSlash) {