Line data Source code
1 : #include "source/common/router/config_utility.h" 2 : 3 : #include <string> 4 : #include <vector> 5 : 6 : #include "envoy/config/core/v3/base.pb.h" 7 : #include "envoy/config/route/v3/route_components.pb.h" 8 : #include "envoy/type/matcher/v3/string.pb.h" 9 : 10 : #include "source/common/common/assert.h" 11 : #include "source/common/common/regex.h" 12 : #include "source/common/config/datasource.h" 13 : 14 : namespace Envoy { 15 : namespace Router { 16 : namespace { 17 : 18 : absl::optional<Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>> 19 58 : maybeCreateStringMatcher(const envoy::config::route::v3::QueryParameterMatcher& config) { 20 58 : switch (config.query_parameter_match_specifier_case()) { 21 38 : case envoy::config::route::v3::QueryParameterMatcher::QueryParameterMatchSpecifierCase:: 22 38 : kStringMatch: 23 38 : return Matchers::StringMatcherImpl(config.string_match()); 24 0 : case envoy::config::route::v3::QueryParameterMatcher::QueryParameterMatchSpecifierCase:: 25 0 : kPresentMatch: 26 0 : return absl::nullopt; 27 20 : case envoy::config::route::v3::QueryParameterMatcher::QueryParameterMatchSpecifierCase:: 28 20 : QUERY_PARAMETER_MATCH_SPECIFIER_NOT_SET: 29 20 : return absl::nullopt; 30 58 : } 31 : 32 0 : return absl::nullopt; 33 58 : } 34 : 35 : } // namespace 36 : 37 : ConfigUtility::QueryParameterMatcher::QueryParameterMatcher( 38 : const envoy::config::route::v3::QueryParameterMatcher& config) 39 58 : : name_(config.name()), matcher_(maybeCreateStringMatcher(config)) {} 40 : 41 : bool ConfigUtility::QueryParameterMatcher::matches( 42 0 : const Http::Utility::QueryParamsMulti& request_query_params) const { 43 : // This preserves the legacy behavior of ignoring all but the first value for a given key 44 0 : auto data = request_query_params.getFirstValue(name_); 45 0 : if (!data.has_value()) { 46 0 : return false; 47 0 : } 48 : 49 0 : if (!matcher_.has_value()) { 50 : // Present check 51 0 : return true; 52 0 : } 53 : 54 0 : return matcher_.value().match(data.value()); 55 0 : } 56 : 57 : Upstream::ResourcePriority 58 1645 : ConfigUtility::parsePriority(const envoy::config::core::v3::RoutingPriority& priority) { 59 1645 : switch (priority) { 60 0 : PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; 61 1641 : case envoy::config::core::v3::DEFAULT: 62 1641 : return Upstream::ResourcePriority::Default; 63 4 : case envoy::config::core::v3::HIGH: 64 4 : return Upstream::ResourcePriority::High; 65 1645 : } 66 0 : PANIC_DUE_TO_CORRUPT_ENUM; 67 0 : } 68 : 69 : bool ConfigUtility::matchQueryParams( 70 : const Http::Utility::QueryParamsMulti& query_params, 71 0 : const std::vector<QueryParameterMatcherPtr>& config_query_params) { 72 0 : for (const auto& config_query_param : config_query_params) { 73 0 : if (!config_query_param->matches(query_params)) { 74 0 : return false; 75 0 : } 76 0 : } 77 : 78 0 : return true; 79 0 : } 80 : 81 : Http::Code ConfigUtility::parseRedirectResponseCode( 82 480 : const envoy::config::route::v3::RedirectAction::RedirectResponseCode& code) { 83 480 : switch (code) { 84 0 : PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; 85 474 : case envoy::config::route::v3::RedirectAction::MOVED_PERMANENTLY: 86 474 : return Http::Code::MovedPermanently; 87 0 : case envoy::config::route::v3::RedirectAction::FOUND: 88 0 : return Http::Code::Found; 89 0 : case envoy::config::route::v3::RedirectAction::SEE_OTHER: 90 0 : return Http::Code::SeeOther; 91 6 : case envoy::config::route::v3::RedirectAction::TEMPORARY_REDIRECT: 92 6 : return Http::Code::TemporaryRedirect; 93 0 : case envoy::config::route::v3::RedirectAction::PERMANENT_REDIRECT: 94 0 : return Http::Code::PermanentRedirect; 95 480 : } 96 0 : PANIC_DUE_TO_CORRUPT_ENUM; 97 0 : } 98 : 99 : absl::optional<Http::Code> 100 1645 : ConfigUtility::parseDirectResponseCode(const envoy::config::route::v3::Route& route) { 101 1645 : if (route.has_redirect()) { 102 480 : return parseRedirectResponseCode(route.redirect().response_code()); 103 1165 : } else if (route.has_direct_response()) { 104 39 : return static_cast<Http::Code>(route.direct_response().status()); 105 39 : } 106 1126 : return {}; 107 1645 : } 108 : 109 : absl::StatusOr<std::string> 110 : ConfigUtility::parseDirectResponseBody(const envoy::config::route::v3::Route& route, Api::Api& api, 111 1645 : uint32_t max_body_size_bytes) { 112 1645 : if (!route.has_direct_response() || !route.direct_response().has_body()) { 113 1606 : return EMPTY_STRING; 114 1606 : } 115 39 : const auto& body = route.direct_response().body(); 116 : 117 39 : const std::string string_body = 118 39 : Envoy::Config::DataSource::read(body, true, api, max_body_size_bytes); 119 39 : if (string_body.length() > max_body_size_bytes) { 120 0 : return absl::InvalidArgumentError(fmt::format("response body size is {} bytes; maximum is {}", 121 0 : string_body.length(), max_body_size_bytes)); 122 0 : } 123 39 : return string_body; 124 39 : } 125 : 126 : Http::Code ConfigUtility::parseClusterNotFoundResponseCode( 127 1645 : const envoy::config::route::v3::RouteAction::ClusterNotFoundResponseCode& code) { 128 1645 : switch (code) { 129 0 : PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; 130 1637 : case envoy::config::route::v3::RouteAction::SERVICE_UNAVAILABLE: 131 1637 : return Http::Code::ServiceUnavailable; 132 4 : case envoy::config::route::v3::RouteAction::NOT_FOUND: 133 4 : return Http::Code::NotFound; 134 4 : case envoy::config::route::v3::RouteAction::INTERNAL_SERVER_ERROR: 135 4 : return Http::Code::InternalServerError; 136 1645 : } 137 0 : PANIC_DUE_TO_CORRUPT_ENUM; 138 0 : } 139 : 140 : } // namespace Router 141 : } // namespace Envoy