Skip to content

Commit

Permalink
router: move regex_rewrite to separate field and fix tests
Browse files Browse the repository at this point in the history
Signed-off-by: Christopher M. Luciano <cmluciano@us.ibm.com>
  • Loading branch information
Christopher M. Luciano committed Nov 25, 2019
1 parent 1d0c788 commit cd64d21
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 78 deletions.
104 changes: 52 additions & 52 deletions api/envoy/api/v2/route/route.proto
Original file line number Diff line number Diff line change
Expand Up @@ -705,46 +705,59 @@ message RouteAction {
// provided there taking precedence. The filter name should be specified as *envoy.lb*.
core.Metadata metadata_match = 4;

oneof path_rewrite_specifier {
// Indicates that during forwarding, the matched prefix (or path) should be
// swapped with this value. This option allows application URLs to be rooted
// at a different path from those exposed at the reverse proxy layer. The router filter will
// place the original path before rewrite into the :ref:`x-envoy-original-path
// <config_http_filters_router_x-envoy-original-path>` header.
//
// .. attention::
//
// Pay careful attention to the use of trailing slashes in the
// :ref:`route's match <envoy_api_field_route.Route.match>` prefix value.
// Stripping a prefix from a path requires multiple Routes to handle all cases. For example,
// rewriting */prefix* to */* and */prefix/etc* to */etc* cannot be done in a single
// :ref:`Route <envoy_api_msg_route.Route>`, as shown by the below config entries:
//
// .. code-block:: yaml
//
// - match:
// prefix: "/prefix/"
// route:
// prefix_rewrite: "/"
// - match:
// prefix: "/prefix"
// route:
// prefix_rewrite: "/"
//
// Having above entries in the config, requests to */prefix* will be stripped to */*, while
// requests to */prefix/etc* will be stripped to */etc*.
string prefix_rewrite = 5;
// Indicates that during forwarding, the matched prefix (or path) should be
// swapped with this value. This option allows application URLs to be rooted
// at a different path from those exposed at the reverse proxy layer. The router filter will
// place the original path before rewrite into the :ref:`x-envoy-original-path
// <config_http_filters_router_x-envoy-original-path>` header.
//
// .. attention::
//
// Pay careful attention to the use of trailing slashes in the
// :ref:`route's match <envoy_api_field_route.Route.match>` prefix value.
// Stripping a prefix from a path requires multiple Routes to handle all cases. For example,
// rewriting */prefix* to */* and */prefix/etc* to */etc* cannot be done in a single
// :ref:`Route <envoy_api_msg_route.Route>`, as shown by the below config entries:
//
// .. code-block:: yaml
//
// - match:
// prefix: "/prefix/"
// route:
// prefix_rewrite: "/"
// - match:
// prefix: "/prefix"
// route:
// prefix_rewrite: "/"
//
// Having above entries in the config, requests to */prefix* will be stripped to */*, while
// requests to */prefix/etc* will be stripped to */etc*.
string prefix_rewrite = 5;

// Indicates that during forwarding, paths that match the pattern should be
// rewritten, interpolating capture groups from the path pattern into the new path as specified
// by the rewrite pattern. This option allows application URLs to be rewritten at the reverse
// proxy layer in a way that is aware of segments with variable contents like IDs. The router
// filter will place the original path before rewrite into the :ref:`x-envoy-original-path //
// <config_http_filters_router_x-envoy-original-path>` header. Examples:
//
// * The path pattern *^/foo/(bar)/(.*)$ paired with rewrite pattern */$1/$2* would transform
// */foo/bar/baz/bang* into */bar/baz/bang*.
//
// [#next-major-version: RegexRewrite should be merged with prefix_rewrite and converted to a oneof.]
RegexRewrite regex_rewrite = 30;

// Indicates that during forwarding, paths that match the pattern should be
// rewritten, interpolating capture groups from the path pattern into the new path as specified
// by the rewrite pattern. This option allows application URLs to be rewritten at the reverse
// proxy layer in a way that is aware of segments with variable contents like IDs. The router
// filter will place the original path before rewrite into the :ref:`x-envoy-original-path //
// <config_http_filters_router_x-envoy-original-path>` header. Examples:
//
// * The path pattern *^/foo/(bar)/(.*)$ paired with rewrite pattern */$1/$2* would transform
// */foo/bar/baz/bang* into */bar/baz/bang*.
RegexRewrite regex_rewrite = 30;
message RegexRewrite {
// Represents a regular expression that the path must match in order for the substitution
// to be applied. The regular expression may include capture groups to be interpolated into the
// substitution.
string pattern = 1;

// Represents the substitution used to build the final path of the request if the initial path
// matches
// the pattern. The substitution may include references to capture groups defined in the
// pattern which will be interpolated into the final path.
string substitution = 2;
}

oneof host_rewrite_specifier {
Expand Down Expand Up @@ -807,19 +820,6 @@ message RouteAction {
// occurs.
google.protobuf.Duration idle_timeout = 24;

message RegexRewrite {
// Represents a regular expression that the path must match in order for the substitution
// to be applied. The regular expression may include capture groups to be interpolated into the
// substitution.
string pattern = 1;

// Represents the substitution used to build the final path of the request if the initial path
// matches
// the pattern. The substitution may include references to capture groups defined in the
// pattern which will be interpolated into the final path.
string substitution = 2;
}

// Indicates that the route has a retry policy. Note that if this is set,
// it'll take precedence over the virtual host level retry policy entirely
// (e.g.: policies are not merged, most internal one becomes the enforced policy).
Expand Down
7 changes: 0 additions & 7 deletions source/common/json/config_schemas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -670,13 +670,6 @@ const std::string Json::Schema::ROUTE_ENTRY_CONFIGURATION_SCHEMA(R"EOF(
"host_redirect" : {"type" : "string"},
"path_redirect" : {"type" : "string"},
"prefix_rewrite" : {"type" : "string"},
"regex_rewrite" : {
"type" : "object",
"properties" : {
"pattern": {"type" : "string"},
"substitution" : {"type" : "integer"}
}
},
"host_rewrite" : {"type" : "string"},
"auto_host_rewrite" : {"type" : "boolean"},
"case_sensitive" : {"type" : "boolean"},
Expand Down
6 changes: 3 additions & 3 deletions source/common/router/config_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -471,16 +471,16 @@ RouteEntryImplBase::loadRuntimeData(const envoy::api::v2::route::RouteMatch& rou
void RouteEntryImplBase::finalizePathHeader(Http::HeaderMap& headers,
absl::string_view matched_path,
bool insert_envoy_original_path) const {
const PathRewriter& path_rewriter = getPathRewriter();
auto path_rewriter = getPathRewriter();

if (!path_rewriter.apply()) {
if (!path_rewriter->apply()) {
return;
} else {
std::string path(headers.Path()->value().getStringView());
if (insert_envoy_original_path) {
headers.setEnvoyOriginalPath(path);
}
headers.setPath()->value(path_rewriter.rewrite(path, matched_path, case_sensitive_));
headers.setPath()->value(path_rewriter->rewrite(path, matched_path, case_sensitive_));
}
}

Expand Down
31 changes: 16 additions & 15 deletions source/common/router/config_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ class RouteTracingImpl : public RouteTracing {
class PathRewriter {
public:
virtual bool apply() const = 0;
virtual std::string rewrite(std::string path, const std::string& matched_path,
virtual std::string rewrite(std::string path, const absl::string_view matched_path,
bool case_sensitive) const = 0;
virtual ~PathRewriter(){};
};
Expand All @@ -376,8 +376,12 @@ class PrefixPathRewriter : public PathRewriter {

bool apply() const { return !prefix_.empty(); }

std::string rewrite(std::string path, const std::string& matched_path,
std::string rewrite(std::string path, const absl::string_view matched_path,
bool case_sensitive) const {
ENVOY_LOG_MISC(debug, "the matched path is: {}", matched_path);
ENVOY_LOG_MISC(debug, "the path is: {}", path);
ENVOY_LOG_MISC(debug, "the case sensitivity is: {}", case_sensitive);
ENVOY_LOG_MISC(debug, "the prefix in PrefixPathRewriter is: {}", prefix_);
ASSERT(case_sensitive ? absl::StartsWith(path, matched_path)
: absl::StartsWithIgnoreCase(path, matched_path));
return path.replace(0, matched_path.size(), prefix_);
Expand All @@ -394,16 +398,16 @@ class PrefixPathRewriter : public PathRewriter {
*/
class RegexPathRewriter : public PathRewriter {
public:
RegexPathRewriter(std::string pattern, std::string substitution)
RegexPathRewriter(std::string pattern, absl::string_view substitution)
: PathRewriter(), pattern_(pattern), substitution_(substitution) {}

bool apply() const { return !substitution_.empty(); }

std::string rewrite(std::string path, const std::string& matched_path,
std::string rewrite(std::string path, const absl::string_view matched_path,
bool case_sensitive) const {
ASSERT(case_sensitive ? absl::StartsWith(path, matched_path)
: absl::StartsWithIgnoreCase(path, matched_path));
return std::regex_replace(matched_path, pattern_, substitution_);
return std::regex_replace(matched_path.data(), pattern_, substitution_);
}

~RegexPathRewriter(){};
Expand All @@ -418,18 +422,15 @@ class RegexPathRewriter : public PathRewriter {
*/
class RewriteBuilder {
public:
static PathRewriter& build(const envoy::api::v2::route::Route& route) {
static std::unique_ptr<PathRewriter> build(const envoy::api::v2::route::Route& route) {
if (!route.redirect().prefix_rewrite().empty()) {
static PrefixPathRewriter p(route.redirect().prefix_rewrite());
return p;
return std::unique_ptr<PathRewriter>(new PrefixPathRewriter(route.redirect().prefix_rewrite()));
}
if (!route.route().prefix_rewrite().empty()) {
static PrefixPathRewriter p(route.route().prefix_rewrite());
return p;
return std::unique_ptr<PathRewriter>(new PrefixPathRewriter(route.route().prefix_rewrite()));
}
static RegexPathRewriter p(route.route().regex_rewrite().pattern(),
route.route().regex_rewrite().substitution());
return p;
return std::unique_ptr<PathRewriter>(new RegexPathRewriter(route.route().regex_rewrite().pattern(),
route.route().regex_rewrite().substitution()));
};
};

Expand Down Expand Up @@ -535,15 +536,15 @@ class RouteEntryImplBase : public RouteEntry,
const bool case_sensitive_;
const std::string prefix_rewrite_;
const std::string host_rewrite_;
const PathRewriter& path_rewriter_;
std::unique_ptr<PathRewriter> path_rewriter_;
bool include_vh_rate_limits_;

RouteConstSharedPtr clusterEntry(const Http::HeaderMap& headers, uint64_t random_value) const;

/**
* returns the path rewriter instance for the route
*/
const PathRewriter& getPathRewriter() const { return path_rewriter_; }
const PathRewriter* getPathRewriter() const { return path_rewriter_.get(); }

void finalizePathHeader(Http::HeaderMap& headers, absl::string_view matched_path,
bool insert_envoy_original_path) const;
Expand Down
2 changes: 1 addition & 1 deletion test/common/router/config_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "envoy/api/v2/rds.pb.validate.h"
#include "envoy/api/v2/route/route.pb.validate.h"
#include "envoy/server/filter_config.h"
#include "envoy/server/filter_config.h"\

#include "common/config/metadata.h"
#include "common/config/well_known_names.h"
Expand Down

0 comments on commit cd64d21

Please sign in to comment.