Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

router: Create InternalRedirectPolicy in side RouteAction and extend it with pluggable predicates #10908

Merged
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
2d1206f
Move internal redirect configs into InternalRedirectPolicy and implement
penguingao Apr 20, 2020
15f1510
Generate protobuf.
penguingao Apr 22, 2020
81debc8
Fix typos.
penguingao Apr 22, 2020
e3eee18
Fix more typo in the comments.
penguingao Apr 22, 2020
c89a6b4
Fix ref links.
penguingao Apr 22, 2020
0f77ae8
Fix link in hcm arch overview.
penguingao Apr 22, 2020
985819a
Fix doc links. For real.
penguingao Apr 22, 2020
8199c60
And fix the formats.
penguingao Apr 23, 2020
fac46f2
Fix typos.
penguingao Apr 23, 2020
fe9e5c9
More typo correction.
penguingao Apr 23, 2020
179e5a9
More typos.
penguingao Apr 23, 2020
1c7ada2
fix clang-tidy findings.
penguingao Apr 23, 2020
925950c
ConfigTest -> PreviousRoutesTest.
penguingao Apr 23, 2020
61e15f7
Format.
penguingao Apr 23, 2020
a806956
Kick CI
penguingao Apr 23, 2020
5711900
Kick CI
penguingao Apr 23, 2020
684ba65
Avoid using newly deprecated fields in the integration test.
penguingao Apr 23, 2020
ad05c9b
Add comments InternalRedirectAction enum values.
penguingao Apr 27, 2020
c606a1e
Run proto_format on proto comment change.
penguingao Apr 27, 2020
feedb0e
Address API comments.
penguingao Apr 29, 2020
b5a1f54
Fix format.
penguingao Apr 29, 2020
23521a6
Address API comments.
penguingao Apr 30, 2020
dabc625
Address code comments. allow_cross_scheme_redirect will be address se…
penguingao Apr 30, 2020
d6d1dce
Change to allow cross scheme redirect by default.
penguingao May 1, 2020
753e046
Fix doc ref links.
penguingao May 1, 2020
9fa3ecd
Merge branch 'master' into internal-redirect-more-options
penguingao May 1, 2020
ceb0fa9
Fix router:config_impl_test
penguingao May 1, 2020
70da0b9
Merge remote-tracking branch 'origin/internal-redirect-more-options' …
penguingao May 1, 2020
68cad35
Merge remote-tracking branch 'upstream/master' into internal-redirect…
penguingao May 1, 2020
f7beb49
Test that invalid response codes are dropped by InternalRedirectPolicy.
penguingao May 4, 2020
bc525c4
Fix typo.
penguingao May 4, 2020
8cd5974
Merge remote-tracking branch 'upstream/master' into internal-redirect…
penguingao May 4, 2020
4e06b6d
regenerate v4 protos.
penguingao May 4, 2020
8c31bf9
Add stats for internal redirect.
penguingao May 4, 2020
db7a8fe
Fix accidentally broken doc format in http_connection_management.rst
penguingao May 4, 2020
cac69d6
Fix comment.
penguingao May 4, 2020
a24ee60
Fix typo. Add counter test in redirection integration test.
penguingao May 4, 2020
c05d049
Merge remote-tracking branch 'upstream/master' into internal-redirect…
penguingao May 4, 2020
1144d82
Update dictionary.
penguingao May 4, 2020
9e08926
NiceMock<MockInternalRedirectPredicate>.
penguingao May 4, 2020
c111425
Bump stats_integration_test bounds.
penguingao May 5, 2020
5be8361
Adjust stats_integration expectation according to CI.
penguingao May 5, 2020
5c1e199
Fix router_test.
penguingao May 5, 2020
8138621
Merge remote-tracking branch 'upstream/master' into internal-redirect…
penguingao May 12, 2020
8461c5f
Move predicate config to use TypedExtensionConfig.
penguingao May 12, 2020
56b0188
Implete OnlyAllowSafeCrossSchemeRedirect internal redirect predicate.
penguingao May 12, 2020
15a4d3f
Fix format.
penguingao May 12, 2020
948ca63
Add OnlyAllowSafeCrossSchemeRedirect predicate to docs. Make sure the
penguingao May 12, 2020
93cd0e6
Fix previous_route_test.
penguingao May 12, 2020
c62f9da
Fix clang tidy finding.
penguingao May 13, 2020
4e660fd
Rename OnlyAllowSafeCrossSchemeRedirect to SafeCrossScheme to get around
penguingao May 13, 2020
416e79e
API comment fix. const vars. Add @param to interface documentation.
penguingao May 13, 2020
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
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ extensions/filters/common/original_src @snowp @klarose
/*/extensions/filters/listener/tls_inspector @piotrsikora @htuch
/*/extensions/grpc_credentials/example @wozz @htuch
/*/extensions/grpc_credentials/file_based_metadata @wozz @htuch
/*/extensions/internal_redirect @alyssawilk @penguingao
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved
/*/extensions/stat_sinks/dog_statsd @taiki45 @jmarantz
/*/extensions/stat_sinks/hystrix @trabetti @jmarantz
/*/extensions/stat_sinks/metrics_service @ramaraochavali @jmarantz
Expand Down
3 changes: 3 additions & 0 deletions api/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ proto_library(
"//envoy/extensions/filters/network/thrift_proxy/v3:pkg",
"//envoy/extensions/filters/network/zookeeper_proxy/v3:pkg",
"//envoy/extensions/filters/udp/dns_filter/v3alpha:pkg",
"//envoy/extensions/internal_redirect/allow_listed_routes/v3:pkg",
"//envoy/extensions/internal_redirect/previous_routes/v3:pkg",
"//envoy/extensions/internal_redirect/safe_cross_scheme/v3:pkg",
"//envoy/extensions/retry/host/omit_host_metadata/v3:pkg",
"//envoy/extensions/retry/priority/previous_priorities/v3:pkg",
"//envoy/extensions/transport_sockets/alts/v3:pkg",
Expand Down
41 changes: 38 additions & 3 deletions api/envoy/config/route/v3/route_components.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ syntax = "proto3";
package envoy.config.route.v3;

import "envoy/config/core/v3/base.proto";
import "envoy/config/core/v3/extension.proto";
import "envoy/config/core/v3/proxy_protocol.proto";
import "envoy/type/matcher/v3/regex.proto";
import "envoy/type/matcher/v3/string.proto";
Expand Down Expand Up @@ -536,7 +537,7 @@ message CorsPolicy {
core.v3.RuntimeFractionalPercent shadow_enabled = 10;
}

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

Expand All @@ -549,6 +550,7 @@ message RouteAction {
}

// Configures :ref:`internal redirect <arch_overview_internal_redirects>` behavior.
// [#next-major-version: remove this definition - it's defined in the InternalRedirectPolicy message.]
mattklein123 marked this conversation as resolved.
Show resolved Hide resolved
enum InternalRedirectAction {
PASS_THROUGH_INTERNAL_REDIRECT = 0;
HANDLE_INTERNAL_REDIRECT = 1;
Expand Down Expand Up @@ -986,7 +988,13 @@ message RouteAction {

repeated UpgradeConfig upgrade_configs = 25;

InternalRedirectAction internal_redirect_action = 26;
// If present, Envoy will try to follow an upstream redirect response instead of proxying the
// response back to the downstream. An upstream redirect response is defined
// by :ref:`redirect_response_codes
// <envoy_api_field_config.route.v3.InternalRedirectPolicy.redirect_response_codes>`.
InternalRedirectPolicy internal_redirect_policy = 34;

InternalRedirectAction internal_redirect_action = 26 [deprecated = true];

// An internal redirect is handled, iff the number of previous internal redirects that a
// downstream request has encountered is lower than this value, and
Expand All @@ -1002,7 +1010,7 @@ message RouteAction {
// will pass the redirect back to downstream.
//
// If not specified, at most one redirect will be followed.
google.protobuf.UInt32Value max_internal_redirects = 31;
google.protobuf.UInt32Value max_internal_redirects = 31 [deprecated = true];

// Indicates that the route has a hedge policy. Note that if this is set,
// it'll take precedence over the virtual host level hedge policy entirely
Expand Down Expand Up @@ -1593,3 +1601,30 @@ message QueryParameterMatcher {
bool present_match = 6;
}
}

// HTTP Internal Redirect :ref:`architecture overview <arch_overview_internal_redirects>`.
message InternalRedirectPolicy {
// An internal redirect is not handled, unless the number of previous internal redirects that a
// downstream request has encountered is lower than this value.
// In the case where a downstream request is bounced among multiple routes by internal redirect,
// the first route that hits this threshold, or does not set :ref:`internal_redirect_policy
// <envoy_api_field_config.route.v3.RouteAction.internal_redirect_policy>`
// will pass the redirect back to downstream.
//
// If not specified, at most one redirect will be followed.
google.protobuf.UInt32Value max_internal_redirects = 1;

// Defines what upstream response codes are allowed to trigger internal redirect. If unspecified,
// only 302 will be treated as internal redirect.
// Only 301, 302, 303, 307 and 308 are valid values. Any other codes will be ignored.
repeated uint32 redirect_response_codes = 2 [(validate.rules).repeated = {max_items: 5}];

// Specifies a list of predicates that are queried when an upstream response is deemed
// to trigger an internal redirect by all other criteria. Any predicate in the list can reject
// the redirect, causing the response to be proxied to downstream.
repeated core.v3.TypedExtensionConfig predicates = 3;

// Allow internal redirect to follow a target URI with a different scheme than the value of
// x-forwarded-proto. Default behavior is to proxy such redirects downstream.
penguingao marked this conversation as resolved.
Show resolved Hide resolved
bool allow_cross_scheme_redirect = 4;
Copy link
Contributor

Choose a reason for hiding this comment

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

What's your plan here?
So the default code base today allows serving secure and insecure content over TLS, and insecure content over raw HTTP.
Either you're coding up a behavioral change which changes the default (doable, but why not leave it permissive and add a predicate if you want to not allow?) or you're making it possible to serve TLS content in the clear which I'd really prefer we not do.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok looking at the code this looks intentional, and I'm not sure how we want to document a difference in the new behavior, i.e. calling out to folks as they migrate that if they want to preserve existing behavior, they need to set something new. It's probably worth sorting out what we want to do in general, though you could bypass that conversation if you invert this and have disallow_cross_scheme_redirect to disallow serving http content over an https channel.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I took the route of using disallow_cross_scheme_redirect to be more permissive.

We have an upstream that receives traffic both directly from end user and from the Envoy. The upstream issues redirect scheme based on the incoming scheme. We would like to have the Envoy -> upstream traffic to always be TLS to protect internal only URL, but it's perfectly fine for the end user to talk to the Envoy in plain text otherwise. So cross scheme redirect is really valuable here:

Admittedly we can make the upstream smarter by looking not only to the tls context but also to x-forwarded-proto header, but the upstream then need to know when to look at x-forwarded-proto and when to not. Since it receives internet traffic, anyone can set such header to confuse it.

}
60 changes: 40 additions & 20 deletions api/envoy/config/route/v4alpha/route_components.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ syntax = "proto3";
package envoy.config.route.v4alpha;

import "envoy/config/core/v4alpha/base.proto";
import "envoy/config/core/v4alpha/extension.proto";
import "envoy/config/core/v4alpha/proxy_protocol.proto";
import "envoy/type/matcher/v4alpha/regex.proto";
import "envoy/type/matcher/v4alpha/string.proto";
Expand Down Expand Up @@ -539,7 +540,7 @@ message CorsPolicy {
core.v4alpha.RuntimeFractionalPercent shadow_enabled = 10;
}

// [#next-free-field: 34]
// [#next-free-field: 35]
message RouteAction {
option (udpa.annotations.versioning).previous_message_type = "envoy.config.route.v3.RouteAction";

Expand All @@ -552,6 +553,7 @@ message RouteAction {
}

// Configures :ref:`internal redirect <arch_overview_internal_redirects>` behavior.
// [#next-major-version: remove this definition - it's defined in the InternalRedirectPolicy message.]
enum InternalRedirectAction {
PASS_THROUGH_INTERNAL_REDIRECT = 0;
HANDLE_INTERNAL_REDIRECT = 1;
Expand Down Expand Up @@ -750,9 +752,9 @@ message RouteAction {
ConnectConfig connect_config = 3;
}

reserved 12, 18, 19, 16, 22, 21, 10;
reserved 12, 18, 19, 16, 22, 21, 10, 26, 31;

reserved "request_mirror_policy";
reserved "request_mirror_policy", "internal_redirect_action", "max_internal_redirects";

oneof cluster_specifier {
option (validate.required) = true;
Expand Down Expand Up @@ -992,23 +994,11 @@ message RouteAction {

repeated UpgradeConfig upgrade_configs = 25;

InternalRedirectAction internal_redirect_action = 26;

// An internal redirect is handled, iff the number of previous internal redirects that a
// downstream request has encountered is lower than this value, and
// :ref:`internal_redirect_action <envoy_api_field_config.route.v4alpha.RouteAction.internal_redirect_action>`
// is set to :ref:`HANDLE_INTERNAL_REDIRECT
// <envoy_api_enum_value_config.route.v4alpha.RouteAction.InternalRedirectAction.HANDLE_INTERNAL_REDIRECT>`
// In the case where a downstream request is bounced among multiple routes by internal redirect,
// the first route that hits this threshold, or has
// :ref:`internal_redirect_action <envoy_api_field_config.route.v4alpha.RouteAction.internal_redirect_action>`
// set to
// :ref:`PASS_THROUGH_INTERNAL_REDIRECT
// <envoy_api_enum_value_config.route.v4alpha.RouteAction.InternalRedirectAction.PASS_THROUGH_INTERNAL_REDIRECT>`
// will pass the redirect back to downstream.
//
// If not specified, at most one redirect will be followed.
google.protobuf.UInt32Value max_internal_redirects = 31;
// If present, Envoy will try to follow an upstream redirect response instead of proxying the
// response back to the downstream. An upstream redirect response is defined
// by :ref:`redirect_response_codes
// <envoy_api_field_config.route.v4alpha.InternalRedirectPolicy.redirect_response_codes>`.
InternalRedirectPolicy internal_redirect_policy = 34;

// Indicates that the route has a hedge policy. Note that if this is set,
// it'll take precedence over the virtual host level hedge policy entirely
Expand Down Expand Up @@ -1603,3 +1593,33 @@ message QueryParameterMatcher {
bool present_match = 6;
}
}

// HTTP Internal Redirect :ref:`architecture overview <arch_overview_internal_redirects>`.
message InternalRedirectPolicy {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.route.v3.InternalRedirectPolicy";

// An internal redirect is not handled, unless the number of previous internal redirects that a
// downstream request has encountered is lower than this value.
// In the case where a downstream request is bounced among multiple routes by internal redirect,
// the first route that hits this threshold, or does not set :ref:`internal_redirect_policy
// <envoy_api_field_config.route.v4alpha.RouteAction.internal_redirect_policy>`
// will pass the redirect back to downstream.
//
// If not specified, at most one redirect will be followed.
google.protobuf.UInt32Value max_internal_redirects = 1;

// Defines what upstream response codes are allowed to trigger internal redirect. If unspecified,
// only 302 will be treated as internal redirect.
// Only 301, 302, 303, 307 and 308 are valid values. Any other codes will be ignored.
repeated uint32 redirect_response_codes = 2 [(validate.rules).repeated = {max_items: 5}];

// Specifies a list of predicates that are queried when an upstream response is deemed
// to trigger an internal redirect by all other criteria. Any predicate in the list can reject
// the redirect, causing the response to be proxied to downstream.
repeated core.v4alpha.TypedExtensionConfig predicates = 3;

// Allow internal redirect to follow a target URI with a different scheme than the value of
// x-forwarded-proto. Default behavior is to proxy such redirects downstream.
bool allow_cross_scheme_redirect = 4;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# DO NOT EDIT. This file is generated by tools/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
syntax = "proto3";

package envoy.extensions.internal_redirect.allow_listed_routes.v3;

import "udpa/annotations/status.proto";
import "udpa/annotations/versioning.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.internal_redirect.allow_listed_routes.v3";
option java_outer_classname = "AllowListedRoutesConfigProto";
option java_multiple_files = true;
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: AllowListed routes internal redirect predicate]
penguingao marked this conversation as resolved.
Show resolved Hide resolved

// An internal redirect predicate that accepts only explicitly allowed target routes.
// [#extension: envoy.internal_redirect_predicates.allow_listed_routes]
message AllowListedRoutesConfig {
// The list of routes that's allowed as redirect target by this predicate,
// identified by the route's :ref:`name <envoy_api_field_config.route.v3.Route.route>`.
// Empty route names are not allowed.
repeated string allowed_route_names = 1
[(validate.rules).repeated = {items {string {min_len: 1}}}];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# DO NOT EDIT. This file is generated by tools/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
syntax = "proto3";

package envoy.extensions.internal_redirect.previous_routes.v3;

import "udpa/annotations/status.proto";
import "udpa/annotations/versioning.proto";

option java_package = "io.envoyproxy.envoy.extensions.internal_redirect.previous_routes.v3";
option java_outer_classname = "PreviousRoutesConfigProto";
option java_multiple_files = true;
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Previous routes internal redirect predicate]

// An internal redirect predicate that rejects redirect targets that are pointing
// to a route that has been followed by a previous redirect from the current route.
// [#extension: envoy.internal_redirect_predicates.previous_routes]
message PreviousRoutesConfig {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# DO NOT EDIT. This file is generated by tools/proto_sync.py.

load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")

licenses(["notice"]) # Apache 2

api_proto_package(
deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
syntax = "proto3";

package envoy.extensions.internal_redirect.safe_cross_scheme.v3;

import "udpa/annotations/status.proto";
import "udpa/annotations/versioning.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.internal_redirect.safe_cross_scheme.v3";
option java_outer_classname = "SafeCrossSchemeConfigProto";
option java_multiple_files = true;
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: SafeCrossScheme internal redirect predicate]

// An internal redirect predicate that checks the scheme between the
// downstream url and the redirect target url and allows a) same scheme
// redirect and b) safe cross scheme redirect, which means if the downstream
// scheme is HTTPS, both HTTPS and HTTP redirect targets are allowed, but if the
// downstream scheme is HTTP, only HTTP redirect targets are allowed.
// [#extension:
// envoy.internal_redirect_predicates.safe_cross_scheme]
message SafeCrossSchemeConfig {
}
3 changes: 3 additions & 0 deletions api/versioning/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ proto_library(
"//envoy/extensions/filters/network/thrift_proxy/v3:pkg",
"//envoy/extensions/filters/network/zookeeper_proxy/v3:pkg",
"//envoy/extensions/filters/udp/dns_filter/v3alpha:pkg",
"//envoy/extensions/internal_redirect/allow_listed_routes/v3:pkg",
"//envoy/extensions/internal_redirect/previous_routes/v3:pkg",
"//envoy/extensions/internal_redirect/safe_cross_scheme/v3:pkg",
"//envoy/extensions/retry/host/omit_host_metadata/v3:pkg",
"//envoy/extensions/retry/priority/previous_priorities/v3:pkg",
"//envoy/extensions/transport_sockets/alts/v3:pkg",
Expand Down
1 change: 1 addition & 0 deletions docs/root/api-v3/config/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ Extensions
grpc_credential/grpc_credential
retry/retry
trace/trace
internal_redirect/internal_redirect
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Internal Redirect Predicates
============================

.. toctree::
:glob:
:maxdepth: 2

../../extensions/internal_redirect/**
53 changes: 38 additions & 15 deletions docs/root/intro/arch_overview/http/http_connection_management.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,37 +151,60 @@ previously attempted priorities.
Internal redirects
--------------------------

Envoy supports handling 302 redirects internally, that is capturing a 302 redirect response,
synthesizing a new request, sending it to the upstream specified by the new route match, and
returning the redirected response as the response to the original request.
Envoy supports handling 3xx redirects internally, that is capturing a configurable 3xx redirect
alyssawilk marked this conversation as resolved.
Show resolved Hide resolved
response, synthesizing a new request, sending it to the upstream specified by the new route match,
and returning the redirected response as the response to the original request.

Internal redirects are configured via the ref:`internal redirect action
<envoy_v3_api_field_config.route.v3.RouteAction.internal_redirect_action>` field and
`max internal redirects <envoy_v3_api_field_config.route.v3.RouteAction.max_internal_redirects>` field in
route configuration. When redirect handling is on, any 302 response from upstream is
subject to the redirect being handled by Envoy.
Internal redirects are configured via the :ref:`internal redirect policy
<envoy_v3_api_field_config.route.v3.RouteAction.internal_redirect_policy>` field in route configuration.
When redirect handling is on, any 3xx response from upstream, that matches
:ref:`redirect_response_codes
<envoy_v3_api_field_config.route.v3.InternalRedirectPolicy.redirect_response_codes>`
is subject to the redirect being handled by Envoy.

For a redirect to be handled successfully it must pass the following checks:

1. Be a 302 response.
2. Have a *location* header with a valid, fully qualified URL matching the scheme of the original request.
1. Have a response code matching one of :ref:`redirect_response_codes
alyssawilk marked this conversation as resolved.
Show resolved Hide resolved
<envoy_v3_api_field_config.route.v3.InternalRedirectPolicy.redirect_response_codes>`, which is
either 302 (by default), or a set of 3xx codes (301, 302, 303, 307, 308).
2. Have a *location* header with a valid, fully qualified URL.
3. The request must have been fully processed by Envoy.
4. The request must not have a body.
5. The number of previously handled internal redirect within a given downstream request does not exceed
`max internal redirects <envoy_v3_api_field_config.route.v3.RouteAction.max_internal_redirects>` of the route
that the request or redirected request is hitting.
5. :ref:`allow_cross_scheme_redirect
<envoy_v3_api_field_config.route.v3.InternalRedirectPolicy.allow_cross_scheme_redirect>` is true (default to false),
or the scheme of the downstream request and the *location* header are the same.
6. The number of previously handled internal redirect within a given downstream request does not
exceed :ref:`max internal redirects
<envoy_v3_api_field_config.route.v3.InternalRedirectPolicy.max_internal_redirects>`
of the route that the request or redirected request is hitting.
7. All :ref:`predicates <envoy_v3_api_field_config.route.v3.InternalRedirectPolicy.predicates>` accept
the target route.

Any failure will result in redirect being passed downstream instead.

Since a redirected request may be bounced between different routes, any route in the chain of redirects that

1. does not have internal redirect enabled
2. or has a `max internal redirects
<envoy_v3_api_field_config.route.v3.RouteAction.max_internal_redirects>`
2. or has a :ref:`max internal redirects
<envoy_v3_api_field_config.route.v3.InternalRedirectPolicy.max_internal_redirects>`
smaller or equal to the redirect chain length when the redirect chain hits it
3. or is disallowed by any of the :ref:`predicates
<envoy_v3_api_field_config.route.v3.InternalRedirectPolicy.predicates>`

will cause the redirect to be passed downstream.

Two predicates can be used to create a DAG that defines the redirect chain, the :ref:`previous routes
<envoy_v3_api_msg_extensions.internal_redirect.previous_routes.v3.PreviousRoutesConfig>` predicate, and
the :ref:`allow_listed_routes
<envoy_v3_api_msg_extensions.internal_redirect.allow_listed_routes.v3.AllowListedRoutesConfig>`.
Specifically, the *allow listed routes* predicate defines edges of individual node in the DAG
and the *previous routes* predicate defines "visited" state of the edges, so that loop can be avoided
if so desired.

A third predicate :ref:`safe_cross_scheme
<envoy_v3_api_msg_extensions.internal_redirect.safe_cross_scheme.v3.SafeCrossSchemeConfig>`
can be used to prevent HTTP -> HTTPS redirect.

Once the redirect has passed these checks, the request headers which were shipped to the original
upstream will be modified by:

Expand Down
Loading