diff --git a/docs/configuration/http_conn_man/route_config/vhost.rst b/docs/configuration/http_conn_man/route_config/vhost.rst index 84ff8cd6efdc..121851448431 100644 --- a/docs/configuration/http_conn_man/route_config/vhost.rst +++ b/docs/configuration/http_conn_man/route_config/vhost.rst @@ -27,7 +27,8 @@ domains *(required, array)* A list of domains (host/authority header) that will be matched to this virtual host. Currently, wildcard matching of the form "\*.foo.com" is not supported, however a special entry "\*" is allowed which will match any host/authority header. Only a single virtual - host in the entire route configuration can match on "\*". + host in the entire route configuration can match on "\*". A domain must be unique across all + virtual hosts or the config will fail to load. :ref:`routes ` *(required, array)* The list of routes that will be matched, in order, for incoming requests. diff --git a/source/common/router/config_impl.cc b/source/common/router/config_impl.cc index 4cf8f8b79aa6..593f52a17b48 100644 --- a/source/common/router/config_impl.cc +++ b/source/common/router/config_impl.cc @@ -244,6 +244,11 @@ RouteMatcher::RouteMatcher(const Json::Object& config, Runtime::Loader& runtime, } default_virtual_host_ = virtual_host; } else { + if (virtual_hosts_.find(domain) != virtual_hosts_.end()) { + throw EnvoyException(fmt::format( + "Only unique values for domains are permitted. Duplicate entry of domain {}", + domain)); + } virtual_hosts_.emplace(domain, virtual_host); } } diff --git a/test/common/router/config_impl_test.cc b/test/common/router/config_impl_test.cc index e68cc49a0471..c7d1a2f53e70 100644 --- a/test/common/router/config_impl_test.cc +++ b/test/common/router/config_impl_test.cc @@ -641,6 +641,40 @@ TEST(RouteMatcherTest, TestBadDefaultConfig) { EXPECT_THROW(ConfigImpl config(loader, runtime, cm), EnvoyException); } +TEST(RouteMatcherTest, TestDuplicateDomainConfig) { + std::string json = R"EOF( +{ + "virtual_hosts": [ + { + "name": "www2", + "domains": ["www.lyft.com"], + "routes": [ + { + "prefix": "/", + "cluster": "www2" + } + ] + }, + { + "name": "www2_staging", + "domains": ["www.lyft.com"], + "routes": [ + { + "prefix": "/", + "cluster": "www2_staging" + } + ] + } + ] +} + )EOF"; + + Json::StringLoader loader(json); + NiceMock runtime; + NiceMock cm; + EXPECT_THROW(ConfigImpl config(loader, runtime, cm), EnvoyException); +} + static Http::HeaderMapImpl genRedirectHeaders(const std::string& host, const std::string& path, bool ssl, bool internal) { Http::HeaderMapImpl headers{