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

Expose fault.http.abort.http_status setting via HTTP header #10294

Merged
merged 43 commits into from
Mar 11, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ec89763
Start implementation of HTTP abort header
Augustyniak Mar 6, 2020
d9caef6
Fix proto field number
Augustyniak Mar 6, 2020
9b28c7d
Apply patch proposed by tool
Augustyniak Mar 6, 2020
31126b4
Apply patch proposed by the tool
Augustyniak Mar 6, 2020
e1cf997
Add missing switch case and method
Augustyniak Mar 6, 2020
c534968
lint fixes
Augustyniak Mar 6, 2020
386cf81
Start using abort provider in fault_filter
Augustyniak Mar 7, 2020
ec19b1a
Fix formatting
Augustyniak Mar 7, 2020
e8657fe
Rename statusCode to status_code
Augustyniak Mar 7, 2020
49042c3
Rename abort_code to abort
Augustyniak Mar 7, 2020
239c406
Add unit test
Augustyniak Mar 7, 2020
a63b408
Rename AbortCodeRequest to AbortRequest
Augustyniak Mar 7, 2020
d20a624
Add doc string
Augustyniak Mar 7, 2020
bd32f55
Update existing fault_filter_test tests
Augustyniak Mar 8, 2020
e3c7ca6
Add unit test
Augustyniak Mar 8, 2020
3cd511b
Fix format
Augustyniak Mar 8, 2020
a43c6ef
Update header faults integration test
Augustyniak Mar 8, 2020
17ed854
Update existing unit tests
Augustyniak Mar 8, 2020
559465e
Use a different HTTP header name
Augustyniak Mar 8, 2020
93a6332
Update documentation
Augustyniak Mar 8, 2020
3483611
Fix test
Augustyniak Mar 8, 2020
28e4cf8
Fix header name
Augustyniak Mar 8, 2020
ac46ced
Use strongly typed Http::Code instead of int
Augustyniak Mar 9, 2020
58e21f7
Update unit test
Augustyniak Mar 9, 2020
97ab5b3
Update tests
Augustyniak Mar 9, 2020
18f9152
format fix
Augustyniak Mar 9, 2020
f337341
Fix docs
Augustyniak Mar 9, 2020
224fa21
http -> HTTP doc strings update
Augustyniak Mar 9, 2020
109531e
Update autogenerated files
Augustyniak Mar 9, 2020
4ba49b7
status_code -> statusCode rename
Augustyniak Mar 10, 2020
08ecf36
Performance optimalizations
Augustyniak Mar 10, 2020
2228f5f
Update docs
Augustyniak Mar 10, 2020
60abf18
add unit tests and use &&
Augustyniak Mar 10, 2020
87c61e8
Reorder
Augustyniak Mar 10, 2020
7db79dc
Better doc strings
Augustyniak Mar 10, 2020
0c21567
:hammer:
Augustyniak Mar 10, 2020
deec559
Add integration test
Augustyniak Mar 10, 2020
5d62ece
Add const
Augustyniak Mar 10, 2020
1c1420f
Update docs
Augustyniak Mar 10, 2020
e647685
Fix docs
Augustyniak Mar 10, 2020
95941c0
fix focs
Augustyniak Mar 11, 2020
26651ab
Fix docs
Augustyniak Mar 11, 2020
651ba63
:hammer:
Augustyniak Mar 11, 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
2 changes: 1 addition & 1 deletion docs/root/configuration/http/http_filters/fault_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ 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 [100, 600).
and must be in the range [200, 600).
Copy link
Member

Choose a reason for hiding this comment

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

Worth pointing out that header_abort needs to be set (and including an RST link back to it).

* 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.
* Response rate limit configuration via the *x-envoy-fault-throughput-response* header. The
Expand Down
17 changes: 11 additions & 6 deletions source/extensions/filters/common/fault/fault_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,22 @@ FaultAbortConfig::FaultAbortConfig(
}

absl::optional<Http::Code>
FaultAbortConfig::HeaderAbortProvider::status_code(const Http::HeaderEntry* header) const {
FaultAbortConfig::HeaderAbortProvider::statusCode(const Http::HeaderEntry* header) const {
absl::optional<Http::Code> ret;
if (header == nullptr) {
return absl::nullopt;
return ret;
}

uint64_t value;
if (!absl::SimpleAtoi(header->value().getStringView(), &value)) {
return absl::nullopt;
uint64_t code;
if (!absl::SimpleAtoi(header->value().getStringView(), &code)) {
return ret;
}

if (code >= 200 and code < 600) {
Copy link
Member

Choose a reason for hiding this comment

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

nit: s/and/&& (some C++ compilers don't support it and it's not widely used), also please add some out of range tests.

ret = static_cast<Http::Code>(code);
}

return static_cast<Http::Code>(value);
return ret;
}

FaultDelayConfig::FaultDelayConfig(
Expand Down
16 changes: 8 additions & 8 deletions source/extensions/filters/common/fault/fault_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ class FaultAbortConfig {
FaultAbortConfig(const envoy::extensions::filters::http::fault::v3::FaultAbort& abort_config);

const envoy::type::v3::FractionalPercent& percentage() const { return percentage_; }
absl::optional<Http::Code> status_code(const Http::HeaderEntry* header) const {
return provider_->status_code(header);
absl::optional<Http::Code> statusCode(const Http::HeaderEntry* header) const {
return provider_->statusCode(header);
}

private:
Expand All @@ -44,28 +44,28 @@ class FaultAbortConfig {

// Return the HTTP status code to use. Optionally passed an HTTP header that may contain the
// HTTP status code depending on the provider implementation.
virtual absl::optional<Http::Code> status_code(const Http::HeaderEntry* header) const PURE;
virtual absl::optional<Http::Code> statusCode(const Http::HeaderEntry* header) const PURE;
};

// Delay provider that uses a fixed delay.
// Delay provider that uses a fixed abort status code.
class FixedAbortProvider : public AbortProvider {
public:
FixedAbortProvider(uint64_t status_code) : status_code_(status_code) {}

// DelayProvider
absl::optional<Http::Code> status_code(const Http::HeaderEntry*) const override {
// AbortProvider
absl::optional<Http::Code> statusCode(const Http::HeaderEntry*) const override {
return static_cast<Http::Code>(status_code_);
}

private:
const uint64_t status_code_;
};

// Abort provider the reads a delay from an HTTP header.
// Abort provider the reads a status code from an HTTP header.
class HeaderAbortProvider : public AbortProvider {
public:
// AbortProvider
absl::optional<Http::Code> status_code(const Http::HeaderEntry* header) const override;
absl::optional<Http::Code> statusCode(const Http::HeaderEntry* header) const override;
};

using AbortProviderPtr = std::unique_ptr<AbortProvider>;
Expand Down
26 changes: 14 additions & 12 deletions source/extensions/filters/http/fault/fault_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ Http::FilterHeadersStatus FaultFilter::decodeHeaders(Http::RequestHeaderMap& hea
return Http::FilterHeadersStatus::StopIteration;
}

auto abort_code = abortHttpStatus(headers);
const auto abort_code = abortHttpStatus(headers);
if (abort_code.has_value()) {
abortWithHTTPStatus(abort_code.value());
return Http::FilterHeadersStatus::StopIteration;
Expand Down Expand Up @@ -222,29 +222,31 @@ bool FaultFilter::faultOverflow() {
}

bool FaultFilter::isDelayEnabled() {
if (fault_settings_->requestDelay() == nullptr) {
const auto request_delay = fault_settings_->requestDelay();
if (request_delay == nullptr) {
return false;
}

if (!downstream_cluster_delay_percent_key_.empty()) {
return config_->runtime().snapshot().featureEnabled(
downstream_cluster_delay_percent_key_, fault_settings_->requestDelay()->percentage());
return config_->runtime().snapshot().featureEnabled(downstream_cluster_delay_percent_key_,
request_delay->percentage());
}
return config_->runtime().snapshot().featureEnabled(
fault_settings_->delayPercentRuntime(), fault_settings_->requestDelay()->percentage());
return config_->runtime().snapshot().featureEnabled(fault_settings_->delayPercentRuntime(),
request_delay->percentage());
}

bool FaultFilter::isAbortEnabled() {
if (fault_settings_->requestAbort() == nullptr) {
const auto request_abort = fault_settings_->requestAbort();
if (request_abort == nullptr) {
return false;
}

if (!downstream_cluster_abort_percent_key_.empty()) {
return config_->runtime().snapshot().featureEnabled(
downstream_cluster_abort_percent_key_, fault_settings_->requestAbort()->percentage());
return config_->runtime().snapshot().featureEnabled(downstream_cluster_abort_percent_key_,
request_abort->percentage());
}
return config_->runtime().snapshot().featureEnabled(
fault_settings_->abortPercentRuntime(), fault_settings_->requestAbort()->percentage());
return config_->runtime().snapshot().featureEnabled(fault_settings_->abortPercentRuntime(),
request_abort->percentage());
}

absl::optional<std::chrono::milliseconds>
Expand Down Expand Up @@ -287,7 +289,7 @@ FaultFilter::abortHttpStatus(const Http::RequestHeaderMap& request_headers) {

// See if the configured abort provider has a default status code, if not there is no abort status
// code (e.g., header configuration and no/invalid header).
auto config_abort = fault_settings_->requestAbort()->status_code(
const auto config_abort = fault_settings_->requestAbort()->statusCode(
request_headers.get(Filters::Common::Fault::HeaderNames::get().AbortRequest));
if (!config_abort.has_value()) {
return absl::nullopt;
Expand Down
6 changes: 3 additions & 3 deletions test/extensions/filters/common/fault/fault_config_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ TEST(FaultConfigTest, FaultAbortHeaderConfig) {
FaultAbortConfig config(proto_config);

// No header.
EXPECT_EQ(absl::nullopt, config.status_code(nullptr));
EXPECT_EQ(absl::nullopt, config.statusCode(nullptr));

// Header with bad data.
Http::TestHeaderMapImpl bad_headers{{"x-envoy-fault-abort-request", "abc"}};
EXPECT_EQ(absl::nullopt, config.status_code(bad_headers.get(HeaderNames::get().AbortRequest)));
EXPECT_EQ(absl::nullopt, config.statusCode(bad_headers.get(HeaderNames::get().AbortRequest)));

// Valid header.
Http::TestHeaderMapImpl good_headers{{"x-envoy-fault-abort-request", "401"}};
EXPECT_EQ(Http::Code::Unauthorized,
config.status_code(good_headers.get(HeaderNames::get().AbortRequest)).value());
config.statusCode(good_headers.get(HeaderNames::get().AbortRequest)).value());
}

TEST(FaultConfigTest, FaultDelayHeaderConfig) {
Expand Down