Line data Source code
1 : #include "source/extensions/path/rewrite/uri_template/uri_template_rewrite.h" 2 : 3 : #include <map> 4 : #include <string> 5 : #include <utility> 6 : #include <vector> 7 : 8 : #include "source/common/http/path_utility.h" 9 : #include "source/extensions/path/match/uri_template/uri_template_match.h" 10 : #include "source/extensions/path/uri_template_lib/uri_template_internal.h" 11 : 12 : #include "absl/status/statusor.h" 13 : #include "absl/strings/str_split.h" 14 : #include "absl/strings/string_view.h" 15 : #include "re2/re2.h" 16 : 17 : namespace Envoy { 18 : namespace Extensions { 19 : namespace UriTemplate { 20 : namespace Rewrite { 21 : 22 : #ifndef SWIG 23 : // Silence warnings about missing initializers for members of LazyRE2. 24 : #pragma GCC diagnostic ignored "-Wmissing-field-initializers" 25 : #endif 26 : 27 : absl::Status 28 44 : UriTemplateRewriter::isCompatiblePathMatcher(Router::PathMatcherSharedPtr path_matcher) const { 29 44 : if (path_matcher == nullptr || path_matcher->name() != Extensions::UriTemplate::Match::NAME) { 30 0 : return absl::InvalidArgumentError(fmt::format("unable to use {} extension without {} extension", 31 0 : Extensions::UriTemplate::Rewrite::NAME, 32 0 : Extensions::UriTemplate::Match::NAME)); 33 0 : } 34 : 35 : // This is needed to match up variable values. 36 : // Validation between extensions as they share rewrite pattern variables. 37 44 : if (!isValidSharedVariableSet(rewrite_pattern_, path_matcher->uriTemplate()).ok()) { 38 0 : return absl::InvalidArgumentError( 39 0 : fmt::format("mismatch between variables in path_match_policy {} and path_rewrite_policy {}", 40 0 : path_matcher->uriTemplate(), rewrite_pattern_)); 41 0 : } 42 : 43 44 : return absl::OkStatus(); 44 44 : } 45 : 46 : absl::StatusOr<std::string> UriTemplateRewriter::rewritePath(absl::string_view pattern, 47 0 : absl::string_view matched_path) const { 48 0 : absl::StatusOr<std::string> regex_pattern = convertPathPatternSyntaxToRegex(matched_path); 49 0 : if (!regex_pattern.ok()) { 50 0 : return absl::InvalidArgumentError("Unable to parse matched_path"); 51 0 : } 52 0 : std::string regex_pattern_str = *std::move(regex_pattern); 53 : 54 : // validated on construction of UriTemplateRewriter 55 0 : RewriteSegments rewrite_pattern_segments = 56 0 : parseRewritePattern(rewrite_pattern_, regex_pattern_str).value(); 57 : 58 0 : RE2 regex = RE2(regex_pattern_str); 59 0 : if (!regex.ok()) { 60 0 : return absl::InternalError("Regex library failed"); 61 0 : } 62 : 63 : // First capture is the whole matched regex pattern. 64 0 : int capture_num = regex.NumberOfCapturingGroups() + 1; 65 0 : std::vector<absl::string_view> captures(capture_num); 66 0 : if (!regex.Match(pattern, /*startpos=*/0, 67 0 : /*endpos=*/pattern.size(), RE2::ANCHOR_BOTH, captures.data(), captures.size())) { 68 0 : return absl::InvalidArgumentError("Pattern not match"); 69 0 : } 70 : 71 0 : std::string new_path; 72 0 : for (const RewriteSegment& segment : rewrite_pattern_segments) { 73 0 : auto* literal = absl::get_if<std::string>(&segment); 74 0 : auto* capture_index = absl::get_if<int>(&segment); 75 0 : if (literal != nullptr) { 76 0 : absl::StrAppend(&new_path, *literal); 77 0 : } else if (capture_index != nullptr) { 78 0 : absl::StrAppend(&new_path, captures[*capture_index]); 79 0 : } 80 0 : } 81 : 82 0 : return {new_path}; 83 0 : } 84 : 85 : } // namespace Rewrite 86 : } // namespace UriTemplate 87 : } // namespace Extensions 88 : } // namespace Envoy