Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 54 additions & 5 deletions api/envoy/config/route/v3/route_components.proto
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ message CorsPolicy {
google.protobuf.BoolValue forward_not_matching_preflights = 13;
}

// [#next-free-field: 43]
// [#next-free-field: 46]
message RouteAction {
option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.route.RouteAction";

Expand Down Expand Up @@ -1181,9 +1181,11 @@ message RouteAction {
// place the original path before rewrite into the :ref:`x-envoy-original-path
// <config_http_filters_router_x-envoy-original-path>` header.
//
// Only one of :ref:`regex_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.regex_rewrite>`
// Only one of :ref:`regex_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.regex_rewrite>`,
// :ref:`path_rewrite_policy <envoy_v3_api_field_config.route.v3.RouteAction.path_rewrite_policy>`,
// or :ref:`prefix_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.prefix_rewrite>` may be specified.
// :ref:`path_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.path_rewrite>`,
// or :ref:`prefix_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.prefix_rewrite>`
// may be specified.
//
// .. attention::
//
Expand Down Expand Up @@ -1219,8 +1221,9 @@ message RouteAction {
// <config_http_filters_router_x-envoy-original-path>` header.
//
// Only one of :ref:`regex_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.regex_rewrite>`,
// :ref:`prefix_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.prefix_rewrite>`, or
// :ref:`path_rewrite_policy <envoy_v3_api_field_config.route.v3.RouteAction.path_rewrite_policy>`]
// :ref:`path_rewrite_policy <envoy_v3_api_field_config.route.v3.RouteAction.path_rewrite_policy>`,
// :ref:`path_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.path_rewrite>`,
// or :ref:`prefix_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.prefix_rewrite>`
// may be specified.
//
// Examples using Google's `RE2 <https://github.com/google/re2>`_ engine:
Expand All @@ -1244,6 +1247,33 @@ message RouteAction {
// [#extension-category: envoy.path.rewrite]
core.v3.TypedExtensionConfig path_rewrite_policy = 41;

// Rewrites the whole path (without query parameters) with the given path value.
// 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.
//
// Only one of :ref:`regex_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.regex_rewrite>`,
// :ref:`path_rewrite_policy <envoy_v3_api_field_config.route.v3.RouteAction.path_rewrite_policy>`,
// :ref:`path_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.path_rewrite>`,
// or :ref:`prefix_rewrite <envoy_v3_api_field_config.route.v3.RouteAction.prefix_rewrite>`
// may be specified.
//
// The :ref:`substitution format specifier <config_access_log_format>` could be applied here.
// For example, with the following config:
//
// .. code-block:: yaml
//
// path_rewrite: "/new_path_prefix%REQ(custom-path-header-name)%"
//
// Would rewrite the path to ``/new_path_prefix/some_value`` given the header
// ``custom-path-header-name: some_value``. If the header is not present, the path will be
// rewritten to ``/new_path_prefix``.
//
//
// If the final output of the path rewrite is empty, then the update will be ignored and the
// original path will be preserved.
string path_rewrite = 45;
Copy link
Member Author

@wbpcode wbpcode Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a general solution for path/host rewriting because it could cover almost all exist features but provide more features, flexibility and extensibility.


// If one of the host rewrite specifiers is set and the
// :ref:`suppress_envoy_headers
// <envoy_v3_api_field_extensions.filters.http.router.v3.Router.suppress_envoy_headers>` flag is not
Expand Down Expand Up @@ -1302,6 +1332,25 @@ message RouteAction {
//
// Would rewrite the host header to ``envoyproxy.io`` given the path ``/envoyproxy.io/some/path``.
type.matcher.v3.RegexMatchAndSubstitute host_rewrite_path_regex = 35;

// Rewrites the host header with the value of this field. The router filter will
// place the original host header value before rewriting into the :ref:`x-envoy-original-host
// <config_http_filters_router_x-envoy-original-host>` header.
//
// The :ref:`substitution format specifier <config_access_log_format>` could be applied here.
// For example, with the following config:
//
// .. code-block:: yaml
//
// host_rewrite: "prefix-%REQ(custom-host-header-name)%"
//
// Would rewrite the host header to ``prefix-some_value`` given the header
// ``custom-host-header-name: some_value``. If the header is not present, the host header will
// be rewritten to an value of ``prefix-``.
//
// If the final output of the host rewrite is empty, then the update will be ignored and the
// original host header will be preserved.
string host_rewrite = 44;
}

// If set, then a host rewrite action (one of
Expand Down
10 changes: 10 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ behavior_changes:

minor_behavior_changes:
# *Changes that may cause incompatibilities for some users, but should not for most*
- area: router
change: |
Added :ref:`host_rewrite
<envoy_v3_api_field_config.route.v3.RouteAction.host_rewrite>` to
:ref:`RouteAction <envoy_v3_api_msg_config.route.v3.RouteAction>` to support substitution
formatting for host header rewriting.
Added :ref:`path_rewrite
<envoy_v3_api_field_config.route.v3.RouteAction.path_rewrite>` to
:ref:`RouteAction <envoy_v3_api_msg_config.route.v3.RouteAction>` to support substitution
formatting for path header rewriting.
- area: ext_proc
change: |
Use one of a hard-coded set of error messages when a :ref:`HeaderMutation
Expand Down
12 changes: 8 additions & 4 deletions envoy/router/router.h
Original file line number Diff line number Diff line change
Expand Up @@ -940,11 +940,15 @@ class RouteEntry : public ResponseEntry {
* using current values of headers. Note that final path may be different if
* headers change before finalization.
* @param headers supplies the request headers.
* @return absl::optional<std::string> the value of the URL path after rewrite or absl::nullopt
* if rewrite is not configured.
* @param context supplies the formatter context for path generation.
* @param stream_info holds additional information about the request.
* @return std::string the value of the URL path after rewrite or empty string
* if rewrite is not configured or rewrite failed.
*/
virtual absl::optional<std::string>
currentUrlPathAfterRewrite(const Http::RequestHeaderMap& headers) const PURE;
virtual std::string
currentUrlPathAfterRewrite(const Http::RequestHeaderMap& headers,
const Formatter::Context& context,
const StreamInfo::StreamInfo& stream_info) const PURE;

/**
* Do potentially destructive header transforms on request headers prior to forwarding. For
Expand Down
4 changes: 2 additions & 2 deletions source/common/http/null_route_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ struct RouteEntryImpl : public Router::RouteEntry {
return Http::Code::InternalServerError;
}
const Router::CorsPolicy* corsPolicy() const override { return nullptr; }
absl::optional<std::string>
currentUrlPathAfterRewrite(const Http::RequestHeaderMap&) const override {
std::string currentUrlPathAfterRewrite(const Http::RequestHeaderMap&, const Formatter::Context&,
const StreamInfo::StreamInfo&) const override {
return {};
}
void finalizeRequestHeaders(Http::RequestHeaderMap&, const Formatter::HttpFormatterContext&,
Expand Down
Loading
Loading