Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fe7807c
implement abort request percentage request
Augustyniak Apr 9, 2020
b422786
format fixes
Augustyniak Apr 9, 2020
11b05a9
fix typo
Augustyniak Apr 9, 2020
29cb061
Add support for 2 more headers
Augustyniak Apr 9, 2020
e712337
update docs
Augustyniak Apr 9, 2020
5cdba2f
update version history
Augustyniak Apr 9, 2020
1d964be
fix percentage call
Augustyniak Apr 9, 2020
7dae973
fix
Augustyniak Apr 9, 2020
5fddbc6
fix
Augustyniak Apr 9, 2020
f29803a
Add tests
Augustyniak Apr 9, 2020
b1cd646
fix
Augustyniak Apr 10, 2020
d48022a
Read headers only if needed
Augustyniak Apr 13, 2020
0008683
Merge remote-tracking branch 'upstream/master' into add-percentage-ht…
Augustyniak Apr 13, 2020
ed6fa7f
fix/improve doc strings
Augustyniak Apr 13, 2020
73b5e2c
revert removal
Augustyniak Apr 13, 2020
9473d45
Remove legacy version_history file
Augustyniak Apr 13, 2020
40f9c58
Remove accidentally commited test
Augustyniak Apr 13, 2020
e65b6ca
Merge remote-tracking branch 'upstream/master' into add-percentage-ht…
Augustyniak Apr 14, 2020
e365cb1
:hammer:
Augustyniak Apr 14, 2020
1d69942
Remove defensive programming checks
Augustyniak Apr 15, 2020
4d7bdf9
Make tests pass
Augustyniak Apr 15, 2020
da2bdb5
Clean up initializer and properties
Augustyniak Apr 15, 2020
1b81ad7
Use the numerator of default percentage
Augustyniak Apr 15, 2020
0d3b05c
Update docs
Augustyniak Apr 15, 2020
dbed763
fix formatting
Augustyniak Apr 15, 2020
3383e5d
Merge remote-tracking branch 'upstream/master' into add-percentage-ht…
Augustyniak Apr 15, 2020
be0db9e
fix order in current.rst
Augustyniak Apr 15, 2020
1ad1368
fix docs
Augustyniak Apr 15, 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
59 changes: 49 additions & 10 deletions docs/root/configuration/http/http_filters/fault_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,58 @@ The fault filter has the capability to allow fault configuration to be specified
This is useful in certain scenarios in which it is desired to allow the client to specify its own
fault configuration. The currently supported header controls are:

* Request abort configuration via the *x-envoy-fault-abort-request* header. The header value
should be an integer that specifies the HTTP status code to return in response to a request
and must be in the range [200, 600). In order for the header to work, :ref:`header_abort
x-envoy-fault-abort-request
HTTP status code to abort a request with. The header value should be an integer that specifies
the HTTP status code to return in response to a request and must be in the range [200, 600).
In order for the header to work, :ref:`header_abort
<envoy_api_field_config.filter.http.fault.v2.FaultAbort.header_abort>` needs to be set.
* Request delay configuration via the *x-envoy-fault-delay-request* header. The header value
should be an integer that specifies the number of milliseconds to throttle the latency for.
In order for the header to work, :ref:`header_delay

x-envoy-fault-abort-request-percentage
The percentage of requests that should be failed with a status code that's defined
by the value of *x-envoy-fault-abort-request* HTTP header. The header value should be an integer
that specifies the numerator of the percentage of request to apply aborts to and must be greater
or equal to 0 and its maximum value is capped by the value of the numerator of
:ref:`percentage <envoy_api_field_config.filter.http.fault.v2.FaultAbort.percentage>` field.
Percentage's denominator is equal to default percentage's denominator
:ref:`percentage <envoy_api_field_config.filter.http.fault.v2.FaultAbort.percentage>` field.
In order for the header to work, :ref:`header_abort
<envoy_api_field_config.filter.http.fault.v2.FaultAbort.header_abort>` needs to be set and
*x-envoy-fault-abort-request* HTTP header needs to be a part of a request.

x-envoy-fault-delay-request
The duration to delay a request by. The header value should be an integer that specifies the number
of milliseconds to throttle the latency for. In order for the header to work, :ref:`header_delay
<envoy_api_field_config.filter.fault.v2.FaultDelay.header_delay>` needs to be set.
* Response rate limit configuration via the *x-envoy-fault-throughput-response* header. The
header value should be an integer that specifies the limit in KiB/s and must be > 0. In order
for the header to work, :ref:`header_limit

x-envoy-fault-delay-request-percentage
The percentage of requests that should be delayed by a duration that's defined by the value of
*x-envoy-fault-delay-request* HTTP header. The header value should be an integer that
specifies the percentage of request to apply delays to and must be greater
or equal to 0 and its maximum value is capped by the value of the numerator of
:ref:`percentage <envoy_api_field_config.filter.fault.v2.FaultDelay.percentage>` field.
Percentage's denominator is equal to default percentage's denominator
:ref:`percentage <envoy_api_field_config.filter.fault.v2.FaultDelay.percentage>` field.
In order for the header to work, :ref:`header_delay
<envoy_api_field_config.filter.fault.v2.FaultDelay.header_delay>` needs to be set and
*x-envoy-fault-delay-request* HTTP header needs to be a part of a request.

x-envoy-fault-throughput-response
The rate limit to use when a response to a caller is sent. The header value should be an integer
that specifies the limit in KiB/s and must be > 0. In order for the header to work, :ref:`header_limit
<envoy_api_field_config.filter.fault.v2.FaultRateLimit.header_limit>` needs to be set.

x-envoy-fault-throughput-response-percentage
The percentage of requests whose response rate should be limited to the value of
*x-envoy-fault-throughput-response* HTTP header. The header value should be an integer that
specifies the percentage of request to apply delays to and must be greater
or equal to 0 and its maximum value is capped by the value of the numerator of
:ref:`percentage <envoy_api_field_config.filter.fault.v2.FaultRateLimit.percentage>` field.
Percentage's denominator is equal to default percentage's denominator
:ref:`percentage <envoy_api_field_config.filter.fault.v2.FaultRateLimit.percentage>` field.
In order for the header to work, :ref:`header_limit
<envoy_api_field_config.filter.fault.v2.FaultRateLimit.header_limit>` needs to be set and
*x-envoy-fault-delay-request* HTTP header needs to be a part of a request.

.. attention::

Allowing header control is inherently dangerous if exposed to untrusted clients. In this case,
Expand Down Expand Up @@ -98,7 +137,7 @@ fault.http.abort.abort_percent
<envoy_api_field_config.filter.http.fault.v2.HTTPFault.abort>`.

fault.http.abort.http_status
HTTP status code that will be used as the of requests that will be
HTTP status code that will be used as the response status code of requests that will be
aborted if the headers match. Defaults to the HTTP status code specified
in the config. If the config does not contain an *abort* block, then
*http_status* defaults to 0. For historic reasons, this runtime key is
Expand Down
2 changes: 2 additions & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Changes
-------

* access loggers: added GRPC_STATUS operator on logging format.
* fault: added support for controlling the percentage of requests that abort, delay and response rate limits faults
are applied to using :ref:`HTTP headers <config_http_filters_fault_injection_http_header>` to the HTTP fault filter.
* http: fixed a bug where the upgrade header was not cleared on responses to non-upgrade requests.
Can be reverted temporarily by setting runtime feature `envoy.reloadable_features.fix_upgrade_response` to false.
* tracing: tracing configuration has been made fully dynamic and every HTTP connection manager
Expand Down
58 changes: 39 additions & 19 deletions source/extensions/filters/common/fault/fault_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,43 @@ namespace Filters {
namespace Common {
namespace Fault {

envoy::type::v3::FractionalPercent
HeaderPercentageProvider::percentage(const Http::RequestHeaderMap* request_headers) const {
const auto header = request_headers->get(header_name_);
if (header == nullptr) {
return percentage_;
}

uint32_t header_numerator;
if (!absl::SimpleAtoi(header->value().getStringView(), &header_numerator)) {
return percentage_;
}

envoy::type::v3::FractionalPercent result;
result.set_numerator(std::min(header_numerator, percentage_.numerator()));
result.set_denominator(percentage_.denominator());
return result;
}

FaultAbortConfig::FaultAbortConfig(
const envoy::extensions::filters::http::fault::v3::FaultAbort& abort_config)
: percentage_(abort_config.percentage()) {
const envoy::extensions::filters::http::fault::v3::FaultAbort& abort_config) {
switch (abort_config.error_type_case()) {
case envoy::extensions::filters::http::fault::v3::FaultAbort::ErrorTypeCase::kHttpStatus:
provider_ = std::make_unique<FixedAbortProvider>(abort_config.http_status());
provider_ =
std::make_unique<FixedAbortProvider>(abort_config.http_status(), abort_config.percentage());
break;
case envoy::extensions::filters::http::fault::v3::FaultAbort::ErrorTypeCase::kHeaderAbort:
provider_ = std::make_unique<HeaderAbortProvider>();
provider_ = std::make_unique<HeaderAbortProvider>(abort_config.percentage());
break;
case envoy::extensions::filters::http::fault::v3::FaultAbort::ErrorTypeCase::ERROR_TYPE_NOT_SET:
NOT_REACHED_GCOVR_EXCL_LINE;
}
}

absl::optional<Http::Code>
FaultAbortConfig::HeaderAbortProvider::statusCode(const Http::HeaderEntry* header) const {
absl::optional<Http::Code> FaultAbortConfig::HeaderAbortProvider::statusCode(
const Http::RequestHeaderMap* request_headers) const {
absl::optional<Http::Code> ret;
const auto header = request_headers->get(HeaderNames::get().AbortRequest);
if (header == nullptr) {
return ret;
}
Expand All @@ -46,26 +65,27 @@ FaultAbortConfig::HeaderAbortProvider::statusCode(const Http::HeaderEntry* heade
}

FaultDelayConfig::FaultDelayConfig(
const envoy::extensions::filters::common::fault::v3::FaultDelay& delay_config)
: percentage_(delay_config.percentage()) {
const envoy::extensions::filters::common::fault::v3::FaultDelay& delay_config) {
switch (delay_config.fault_delay_secifier_case()) {
case envoy::extensions::filters::common::fault::v3::FaultDelay::FaultDelaySecifierCase::
kFixedDelay:
provider_ = std::make_unique<FixedDelayProvider>(
std::chrono::milliseconds(PROTOBUF_GET_MS_REQUIRED(delay_config, fixed_delay)));
std::chrono::milliseconds(PROTOBUF_GET_MS_REQUIRED(delay_config, fixed_delay)),
delay_config.percentage());
break;
case envoy::extensions::filters::common::fault::v3::FaultDelay::FaultDelaySecifierCase::
kHeaderDelay:
provider_ = std::make_unique<HeaderDelayProvider>();
provider_ = std::make_unique<HeaderDelayProvider>(delay_config.percentage());
break;
case envoy::extensions::filters::common::fault::v3::FaultDelay::FaultDelaySecifierCase::
FAULT_DELAY_SECIFIER_NOT_SET:
NOT_REACHED_GCOVR_EXCL_LINE;
}
}

absl::optional<std::chrono::milliseconds>
FaultDelayConfig::HeaderDelayProvider::duration(const Http::HeaderEntry* header) const {
absl::optional<std::chrono::milliseconds> FaultDelayConfig::HeaderDelayProvider::duration(
const Http::RequestHeaderMap* request_headers) const {
const auto header = request_headers->get(HeaderNames::get().DelayRequest);
if (header == nullptr) {
return absl::nullopt;
}
Expand All @@ -79,24 +99,24 @@ FaultDelayConfig::HeaderDelayProvider::duration(const Http::HeaderEntry* header)
}

FaultRateLimitConfig::FaultRateLimitConfig(
const envoy::extensions::filters::common::fault::v3::FaultRateLimit& rate_limit_config)
: percentage_(rate_limit_config.percentage()) {
const envoy::extensions::filters::common::fault::v3::FaultRateLimit& rate_limit_config) {
switch (rate_limit_config.limit_type_case()) {
case envoy::extensions::filters::common::fault::v3::FaultRateLimit::LimitTypeCase::kFixedLimit:
provider_ =
std::make_unique<FixedRateLimitProvider>(rate_limit_config.fixed_limit().limit_kbps());
provider_ = std::make_unique<FixedRateLimitProvider>(
rate_limit_config.fixed_limit().limit_kbps(), rate_limit_config.percentage());
break;
case envoy::extensions::filters::common::fault::v3::FaultRateLimit::LimitTypeCase::kHeaderLimit:
provider_ = std::make_unique<HeaderRateLimitProvider>();
provider_ = std::make_unique<HeaderRateLimitProvider>(rate_limit_config.percentage());
break;
case envoy::extensions::filters::common::fault::v3::FaultRateLimit::LimitTypeCase::
LIMIT_TYPE_NOT_SET:
NOT_REACHED_GCOVR_EXCL_LINE;
}
}

absl::optional<uint64_t>
FaultRateLimitConfig::HeaderRateLimitProvider::rateKbps(const Http::HeaderEntry* header) const {
absl::optional<uint64_t> FaultRateLimitConfig::HeaderRateLimitProvider::rateKbps(
const Http::RequestHeaderMap* request_headers) const {
const auto header = request_headers->get(HeaderNames::get().ThroughputResponse);
if (header == nullptr) {
return absl::nullopt;
}
Expand Down
Loading