in source/common/config/rds_json.cc [205:353]
void RdsJson::translateRoute(const Json::Object& json_route, envoy::api::v2::route::Route& route) {
json_route.validateSchema(Json::Schema::ROUTE_ENTRY_CONFIGURATION_SCHEMA);
auto* match = route.mutable_match();
// This is a trick to do a three-way XOR.
if ((json_route.hasObject("prefix") + json_route.hasObject("path") +
json_route.hasObject("regex")) != 1) {
throw EnvoyException("routes must specify one of prefix/path/regex");
}
if (json_route.hasObject("prefix")) {
match->set_prefix(json_route.getString("prefix"));
} else if (json_route.hasObject("path")) {
match->set_path(json_route.getString("path"));
} else {
ASSERT(json_route.hasObject("regex"));
match->set_regex(json_route.getString("regex"));
}
JSON_UTIL_SET_BOOL(json_route, *match, case_sensitive);
if (json_route.hasObject("runtime")) {
BaseJson::translateRuntimeFraction(*json_route.getObject("runtime"),
*match->mutable_runtime_fraction());
}
for (const auto json_header_matcher : json_route.getObjectArray("headers", true)) {
auto* header_matcher = match->mutable_headers()->Add();
translateHeaderMatcher(*json_header_matcher, *header_matcher);
}
for (const auto json_query_parameter_matcher :
json_route.getObjectArray("query_parameters", true)) {
auto* query_parameter_matcher = match->mutable_query_parameters()->Add();
translateQueryParameterMatcher(*json_query_parameter_matcher, *query_parameter_matcher);
}
bool has_redirect = false;
if (json_route.hasObject("host_redirect") || json_route.hasObject("path_redirect")) {
has_redirect = true;
auto* redirect = route.mutable_redirect();
JSON_UTIL_SET_STRING(json_route, *redirect, host_redirect);
JSON_UTIL_SET_STRING(json_route, *redirect, path_redirect);
}
const bool has_cluster = json_route.hasObject("cluster") ||
json_route.hasObject("cluster_header") ||
json_route.hasObject("weighted_clusters");
if (has_cluster && has_redirect) {
throw EnvoyException("routes must be either redirects or cluster targets");
} else if (!has_cluster && !has_redirect) {
throw EnvoyException(
"routes must have redirect or one of cluster/cluster_header/weighted_clusters");
} else if (has_cluster) {
auto* action = route.mutable_route();
if (json_route.hasObject("cluster")) {
JSON_UTIL_SET_STRING(json_route, *action, cluster);
} else if (json_route.hasObject("cluster_header")) {
JSON_UTIL_SET_STRING(json_route, *action, cluster_header);
} else {
ASSERT(json_route.hasObject("weighted_clusters"));
translateWeightedCluster(*json_route.getObject("weighted_clusters"),
*action->mutable_weighted_clusters());
}
// This is a trick to do a three-way XOR. It would be nice if we could do this with the JSON
// schema but there is no obvious way to do this.
if ((json_route.hasObject("cluster") + json_route.hasObject("cluster_header") +
json_route.hasObject("weighted_clusters")) != 1) {
throw EnvoyException("routes must specify one of cluster/cluster_header/weighted_clusters");
}
JSON_UTIL_SET_STRING(json_route, *action, prefix_rewrite);
if (json_route.hasObject("host_rewrite")) {
JSON_UTIL_SET_STRING(json_route, *action, host_rewrite);
if (json_route.hasObject("auto_host_rewrite")) {
throw EnvoyException(
"routes cannot have both auto_host_rewrite and host_rewrite options set");
}
}
if (json_route.hasObject("auto_host_rewrite")) {
JSON_UTIL_SET_BOOL(json_route, *action, auto_host_rewrite);
}
JSON_UTIL_SET_DURATION(json_route, *action, timeout);
if (json_route.hasObject("retry_policy")) {
auto* retry_policy = action->mutable_retry_policy();
const auto json_retry_policy = json_route.getObject("retry_policy");
JSON_UTIL_SET_STRING(*json_retry_policy, *retry_policy, retry_on);
JSON_UTIL_SET_INTEGER(*json_retry_policy, *retry_policy, num_retries);
JSON_UTIL_SET_DURATION(*json_retry_policy, *retry_policy, per_try_timeout);
}
if (json_route.hasObject("shadow")) {
auto* request_mirror_policy = action->mutable_request_mirror_policy();
const auto json_shadow = json_route.getObject("shadow");
JSON_UTIL_SET_STRING(*json_shadow, *request_mirror_policy, cluster);
JSON_UTIL_SET_STRING(*json_shadow, *request_mirror_policy, runtime_key);
}
envoy::api::v2::core::RoutingPriority priority{};
RoutingPriority_Parse(StringUtil::toUpper(json_route.getString("priority", "default")),
&priority);
action->set_priority(priority);
for (const auto header_value : json_route.getObjectArray("request_headers_to_add", true)) {
auto* header_value_option = action->mutable_request_headers_to_add()->Add();
BaseJson::translateHeaderValueOption(*header_value, *header_value_option);
}
for (const auto json_rate_limit : json_route.getObjectArray("rate_limits", true)) {
auto* rate_limit = action->mutable_rate_limits()->Add();
translateRateLimit(*json_rate_limit, *rate_limit);
}
JSON_UTIL_SET_BOOL(json_route, *action, include_vh_rate_limits);
if (json_route.hasObject("hash_policy")) {
const std::string header_name = json_route.getObject("hash_policy")->getString("header_name");
action->mutable_hash_policy()->Add()->mutable_header()->set_header_name(header_name);
}
if (json_route.hasObject("cors")) {
auto* cors = action->mutable_cors();
const auto json_cors = json_route.getObject("cors");
translateCors(*json_cors, *cors);
}
}
if (json_route.hasObject("opaque_config")) {
const Json::ObjectSharedPtr obj = json_route.getObject("opaque_config");
auto& filter_metadata =
(*route.mutable_metadata()
->mutable_filter_metadata())[Extensions::HttpFilters::HttpFilterNames::get().Router];
obj->iterate([&filter_metadata](const std::string& name, const Json::Object& value) {
(*filter_metadata.mutable_fields())[name].set_string_value(value.asString());
return true;
});
}
if (json_route.hasObject("decorator")) {
auto* decorator = route.mutable_decorator();
translateDecorator(*json_route.getObject("decorator"), *decorator);
}
}