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

fault injection: add support for setting gRPC status #10841

Merged
merged 10 commits into from
Apr 27, 2020
10 changes: 9 additions & 1 deletion api/envoy/extensions/filters/http/fault/v3/fault.proto
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
// Fault Injection :ref:`configuration overview <config_http_filters_fault_injection>`.
// [#extension: envoy.filters.http.fault]

// [#next-free-field: 6]
message FaultAbort {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.filter.http.fault.v2.FaultAbort";
Expand All @@ -41,6 +42,9 @@ message FaultAbort {
// HTTP status code to use to abort the HTTP request.
uint32 http_status = 2 [(validate.rules).uint32 = {lt: 600 gte: 200}];

// gRPC status code to use to abort the gRPC request.
uint32 grpc_status = 5 [(validate.rules).uint32 = {lte: 16}];
Copy link
Member

Choose a reason for hiding this comment

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

I think we should drop the "lte" restriction here so that we can test unknown gRPC codes above those well defined. This is a really common source of bugs (including in envoy itself) so it will be nice to be able to test this. I might clarify in the docs that we allow testing any numeric code, even those that are not well defined. (docs need updating also)


// Fault aborts are controlled via an HTTP header (if applicable).
HeaderAbort header_abort = 4;
}
Expand All @@ -50,7 +54,7 @@ message FaultAbort {
type.v3.FractionalPercent percentage = 3;
}

// [#next-free-field: 14]
// [#next-free-field: 15]
message HTTPFault {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.filter.http.fault.v2.HTTPFault";
Expand Down Expand Up @@ -133,4 +137,8 @@ message HTTPFault {
// The runtime key to override the :ref:`default <config_http_filters_fault_injection_runtime>`
// runtime. The default is: fault.http.rate_limit.response_percent
string response_rate_limit_percent_runtime = 13;

// The runtime key to override the :ref:`default <config_http_filters_fault_injection_runtime>`
// runtime. The default is: fault.http.abort.grpc_status
string abort_grpc_status_runtime = 14;
}
14 changes: 14 additions & 0 deletions docs/root/configuration/http/http_filters/fault_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ x-envoy-fault-abort-request
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.

x-envoy-fault-abort-grpc-request
Copy link
Member

Choose a reason for hiding this comment

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

Should we have a % header here also? cc @Augustyniak

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I think that we should add a support for x-envoy-fault-abort-grpc-request-percentage HTTP header (whose implementation would be based of how x-envoy-fault-abort-request-percentage HTTP header is defined).

Together with @buildbreaker @murki we discussed potential scenarios where having x-envoy-fault-abort-grpc-request-percentage HTTP header would be helpful to test client-side implementation of some of the GRPC requests that Lyft mobile applications perform. This lets me believe that the addition of such header will be useful for engineers from other companies too.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry I missed one thing when I posted my initial comment here.

Initially, I thought that GRPC aborts would be applied on top of http aborts meaning something like:

  1. Requests comes in
  2. Check whether to abort the request with http fault - look at x-envoy-fault-abort-request-percentage and x-envoy-fault-abort-request HTTP headers.
  3. If no http fault was applied (because percentage was <100% and we decided not to apply HTTP fault) check whether grpc faults should be applied - look at x-envoy-fault-abort-grpc-request-percentage and x-envoy-fault-abort-grpc-request HTTP headers.

and for this reason I thought that we needed the addition of x-envoy-fault-abort-grpc-request-percentage HTTP header.

Now that I know that the implementation looks more like apply "either HTTP or GRPC abort" (only one of them) I don't see any benefits of us having x-envoy-fault-abort-grpc-request-percentage HTTP header. Don't get me wrong, as far as I can tell current implementation works correctly and it unlocks GRPC abort tests for mobile people at Lyft but the addition of x-envoy-fault-abort-grpc-request-percentage HTTP header itself doesn't add any value in here - we could continue to use x-envoy-fault-abort-request-percentage HTTP request header and functionality-wise we wouldn't lose anything. We could keep it but I think that removal makes a little more sense since it would keep the implementation simpler.

I really feel bad asking you to do this @vijayrajput1 but could we get rid of x-envoy-fault-abort-grpc-request-percentage HTTP header and use x-envoy-fault-abort-request-percentage for both HTTP and GRPC aborts? My deep apologizes here - I know that the addition of this header costed you a significant amount of work in the first place so it really feels bad to ask you to revert some of your changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you @Augustyniak , I actually had this (using one header) approach in mind earlier but then I kinda convinced myself having a matching header would make things more clear. Meaning use x-envoy-fault-abort-grpc-request-percentage for x-envoy-fault-abort-grpc-request vs use x-envoy-fault-abort-request-percentage for x-envoy-fault-abort-grpc-request. I should have raised this point earlier. I'm okay, with either of those approaches - my take is if having a separate header x-envoy-fault-abort-grpc-request-percentage isn't making things anymore clear than we should use only one header i.e x-envoy-fault-abort-request-percentage - @mattklein123 any preference ?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah agreed on using 1 header. Sorry, I didn't look very deeply at this before punting review over to @Augustyniak. Apologies also!

gRPC status code to abort a request with. The header value should be an integer that specifies
the gRPC status code to return in response to a request and must be in the range [0, 16].
When this header is set, the HTTP response status code will be set to 200. 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.

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
Expand Down Expand Up @@ -144,6 +150,14 @@ fault.http.abort.http_status
available regardless of whether the filter is :ref:`configured for abort
<envoy_api_field_config.filter.http.fault.v2.HTTPFault.abort>`.

fault.http.abort.grpc_status
gRPC status code that will be used as the response status code of requests that will be
aborted if the headers match. Defaults to the gRPC status code specified
in the config. If this field is missing from both the runtime and the config,
gRPC status code in the response will be derived from *fault.http.abort.http_status* field.
This runtime key is only available when the filter is :ref:`configured for abort
<envoy_api_field_config.filter.http.fault.v2.HTTPFault.abort>`.

fault.http.delay.fixed_delay_percent
% of requests that will be delayed if the headers match. Defaults to the
*delay_percent* specified in the config or 0 otherwise. This runtime key is only available when
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 @@ -8,6 +8,8 @@ Changes
* dynamic forward proxy: added :ref:`SNI based dynamic forward proxy <config_network_filters_sni_dynamic_forward_proxy>` support.
* 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.
* fault: added support for specifying grpc_status code in abort faults using
:ref:`HTTP header <config_http_filters_fault_injection_http_header>` or abort fault configuration in HTTP fault filter.
* filter: add `upstram_rq_time` stats to the GPRC stats filter.
Disabled by default and can be enabled via :ref:`enable_upstream_stats <envoy_v3_api_field_extensions.filters.http.grpc_stats.v3.FilterConfig.enable_upstream_stats>`.
* http: fixed a bug where the upgrade header was not cleared on responses to non-upgrade requests.
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 30 additions & 5 deletions source/extensions/filters/common/fault/fault_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,14 @@ FaultAbortConfig::FaultAbortConfig(
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(), abort_config.percentage());
std::make_unique<FixedAbortProvider>(static_cast<Http::Code>(abort_config.http_status()),
absl::nullopt, abort_config.percentage());
break;
case envoy::extensions::filters::http::fault::v3::FaultAbort::ErrorTypeCase::kGrpcStatus:
// If gRPC status code is set, then HTTP will be set to 200
provider_ = std::make_unique<FixedAbortProvider>(
Http::Code::OK, static_cast<Grpc::Status::GrpcStatus>(abort_config.grpc_status()),
abort_config.percentage());
break;
case envoy::extensions::filters::http::fault::v3::FaultAbort::ErrorTypeCase::kHeaderAbort:
provider_ = std::make_unique<HeaderAbortProvider>(abort_config.percentage());
Expand All @@ -44,10 +51,9 @@ FaultAbortConfig::FaultAbortConfig(
}
}

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);
absl::optional<Http::Code>
FaultAbortConfig::HeaderAbortProvider::httpStatusCode(const Http::HeaderEntry* header) const {
absl::optional<Http::Code> ret = absl::nullopt;
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that we need = absl::nullopt part here - I think that we should get rid of it if it's not needed.

Copy link
Contributor Author

@vijayrajput1 vijayrajput1 Apr 27, 2020

Choose a reason for hiding this comment

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

Yep its not required, I put that in there to make it apparent. I had to read absl::optional default details to find out this, so I thought making it apparent might help readability. I can remove it if its something basic.

Copy link
Member

Choose a reason for hiding this comment

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

It's fine either way. I wouldn't worry about it unless we need another push.

if (header == nullptr) {
return ret;
}
Expand All @@ -64,6 +70,25 @@ absl::optional<Http::Code> FaultAbortConfig::HeaderAbortProvider::statusCode(
return ret;
}

absl::optional<Grpc::Status::GrpcStatus>
FaultAbortConfig::HeaderAbortProvider::grpcStatusCode(const Http::HeaderEntry* header) const {
absl::optional<Grpc::Status::GrpcStatus> ret = absl::nullopt;
if (header == nullptr) {
return ret;
}

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

if (code <= 16) {
ret = static_cast<Grpc::Status::GrpcStatus>(code);
}

return ret;
}

FaultDelayConfig::FaultDelayConfig(
const envoy::extensions::filters::common::fault::v3::FaultDelay& delay_config) {
switch (delay_config.fault_delay_secifier_case()) {
Expand Down
49 changes: 35 additions & 14 deletions source/extensions/filters/common/fault/fault_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "envoy/extensions/filters/common/fault/v3/fault.pb.h"
#include "envoy/extensions/filters/http/fault/v3/fault.pb.h"
#include "envoy/grpc/status.h"
#include "envoy/http/header_map.h"
#include "envoy/type/v3/percent.pb.h"

Expand All @@ -20,6 +21,7 @@ class HeaderNameValues {
const char* prefix() { return ThreadSafeSingleton<Http::PrefixValue>::get().prefix(); }

const Http::LowerCaseString AbortRequest{absl::StrCat(prefix(), "-fault-abort-request")};
const Http::LowerCaseString AbortGrpcRequest{absl::StrCat(prefix(), "-fault-abort-grpc-request")};
const Http::LowerCaseString AbortRequestPercentage{
absl::StrCat(prefix(), "-fault-abort-request-percentage")};
const Http::LowerCaseString DelayRequest{absl::StrCat(prefix(), "-fault-delay-request")};
Expand Down Expand Up @@ -53,8 +55,11 @@ class FaultAbortConfig {
public:
FaultAbortConfig(const envoy::extensions::filters::http::fault::v3::FaultAbort& abort_config);

absl::optional<Http::Code> statusCode(const Http::RequestHeaderMap* request_headers) const {
return provider_->statusCode(request_headers);
absl::optional<Http::Code> httpStatusCode(const Http::HeaderEntry* header) const {
return provider_->httpStatusCode(header);
}
absl::optional<Grpc::Status::GrpcStatus> grpcStatusCode(const Http::HeaderEntry* header) const {
return provider_->grpcStatusCode(header);
}

envoy::type::v3::FractionalPercent
Expand All @@ -70,31 +75,44 @@ class FaultAbortConfig {

// Return the HTTP status code to use. Optionally passed HTTP headers that may contain the
// HTTP status code depending on the provider implementation.
virtual absl::optional<Http::Code>
statusCode(const Http::RequestHeaderMap* request_headers) const PURE;
virtual absl::optional<Http::Code> httpStatusCode(const Http::HeaderEntry* header) const PURE;
Copy link
Member

Choose a reason for hiding this comment

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

Why not continue to pass the full header map here and below? It seems like it would be more clear if the header was referenced closer to where it is used?


// Return the gRPC status code to use. Optionally passed an HTTP header that may contain the
// gRPC status code depending on the provider implementation.
virtual absl::optional<Grpc::Status::GrpcStatus>
grpcStatusCode(const Http::HeaderEntry* header) const PURE;

// Return what percentage of requests abort faults should be applied to. Optionally passed
// HTTP headers that may contain the percentage depending on the provider implementation.
virtual envoy::type::v3::FractionalPercent
percentage(const Http::RequestHeaderMap* request_headers) const PURE;
};

// Delay provider that uses a fixed abort status code.
// Abort provider that uses a fixed abort status code.
class FixedAbortProvider : public AbortProvider {
public:
FixedAbortProvider(uint64_t status_code, const envoy::type::v3::FractionalPercent& percentage)
: status_code_(status_code), percentage_(percentage) {}
FixedAbortProvider(Http::Code http_status_code,
absl::optional<Grpc::Status::GrpcStatus> grpc_status_code,
const envoy::type::v3::FractionalPercent& percentage)
: http_status_code_(http_status_code), grpc_status_code_(grpc_status_code),
percentage_(percentage) {}

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

absl::optional<Grpc::Status::GrpcStatus>
grpcStatusCode(const Http::HeaderEntry*) const override {
return grpc_status_code_;
}

envoy::type::v3::FractionalPercent percentage(const Http::RequestHeaderMap*) const override {
return percentage_;
}

private:
const uint64_t status_code_;
const absl::optional<Http::Code> http_status_code_;
const absl::optional<Grpc::Status::GrpcStatus> grpc_status_code_;
const envoy::type::v3::FractionalPercent percentage_;
};

Expand All @@ -103,9 +121,11 @@ class FaultAbortConfig {
public:
HeaderAbortProvider(const envoy::type::v3::FractionalPercent& percentage)
: HeaderPercentageProvider(HeaderNames::get().AbortRequestPercentage, percentage) {}
// AbortProvider
absl::optional<Http::Code>
statusCode(const Http::RequestHeaderMap* request_headers) const override;

absl::optional<Http::Code> httpStatusCode(const Http::HeaderEntry* header) const override;

absl::optional<Grpc::Status::GrpcStatus>
grpcStatusCode(const Http::HeaderEntry*) const override;

envoy::type::v3::FractionalPercent
percentage(const Http::RequestHeaderMap* request_headers) const override {
Expand Down Expand Up @@ -180,6 +200,7 @@ class FaultDelayConfig {
public:
HeaderDelayProvider(const envoy::type::v3::FractionalPercent& percentage)
: HeaderPercentageProvider(HeaderNames::get().DelayRequestPercentage, percentage) {}

// DelayProvider
absl::optional<std::chrono::milliseconds>
duration(const Http::RequestHeaderMap* request_headers) const override;
Expand Down
77 changes: 57 additions & 20 deletions source/extensions/filters/http/fault/fault_filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ FaultSettings::FaultSettings(const envoy::extensions::filters::http::fault::v3::
RuntimeKeys::get().DelayDurationKey)),
abort_http_status_runtime_(PROTOBUF_GET_STRING_OR_DEFAULT(
fault, abort_http_status_runtime, RuntimeKeys::get().AbortHttpStatusKey)),
abort_grpc_status_runtime_(PROTOBUF_GET_STRING_OR_DEFAULT(
fault, abort_grpc_status_runtime, RuntimeKeys::get().AbortGrpcStatusKey)),
max_active_faults_runtime_(PROTOBUF_GET_STRING_OR_DEFAULT(
fault, max_active_faults_runtime, RuntimeKeys::get().MaxActiveFaultsKey)),
response_rate_limit_percent_runtime_(
Expand Down Expand Up @@ -164,9 +166,12 @@ Http::FilterHeadersStatus FaultFilter::decodeHeaders(Http::RequestHeaderMap& hea
return Http::FilterHeadersStatus::StopIteration;
}

const auto abort_code = abortHttpStatus(headers);
if (abort_code.has_value()) {
abortWithHTTPStatus(abort_code.value());
absl::optional<Http::Code> http_status;
absl::optional<Grpc::Status::GrpcStatus> grpc_status;
std::tie(http_status, grpc_status) = abortStatus(headers);

if (http_status.has_value()) {
abortWithStatus(http_status.value(), grpc_status);
return Http::FilterHeadersStatus::StopIteration;
}

Expand Down Expand Up @@ -284,29 +289,57 @@ FaultFilter::delayDuration(const Http::RequestHeaderMap& request_headers) {
return ret;
}

absl::optional<Http::Code>
FaultFilter::abortHttpStatus(const Http::RequestHeaderMap& request_headers) {
AbortHttpAndGrpcStatus FaultFilter::abortStatus(const Http::RequestHeaderMap& request_headers) {
if (!isAbortEnabled(request_headers)) {
return absl::nullopt;
return std::make_pair(absl::nullopt, absl::nullopt);
}

auto grpc_status = abortGrpcStatus(request_headers);

// If gRPC status code is set, then HTTP will be set to 200
return grpc_status.has_value() ? std::make_pair(Http::Code::OK, grpc_status)
: std::make_pair(abortHttpStatus(request_headers), grpc_status);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we pass absl::nullptr instead of grpc_status here to make it clearer that we don't return GRPC status code when we return an HTTP status code from abortHttpStatus(request_headers) ?

}

absl::optional<Http::Code>
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).
const auto config_abort = fault_settings_->requestAbort()->statusCode(&request_headers);
if (!config_abort.has_value()) {
auto http_status = fault_settings_->requestAbort()->httpStatusCode(
request_headers.get(Filters::Common::Fault::HeaderNames::get().AbortRequest));
if (!http_status.has_value()) {
return absl::nullopt;
}

auto status_code = static_cast<uint64_t>(config_abort.value());
auto code = static_cast<Http::Code>(config_->runtime().snapshot().getInteger(
fault_settings_->abortHttpStatusRuntime(), status_code));
auto default_http_status_code = static_cast<uint64_t>(http_status.value());
auto runtime_http_status_code = static_cast<Http::Code>(config_->runtime().snapshot().getInteger(
fault_settings_->abortHttpStatusRuntime(), default_http_status_code));

if (!downstream_cluster_abort_http_status_key_.empty()) {
code = static_cast<Http::Code>(config_->runtime().snapshot().getInteger(
downstream_cluster_abort_http_status_key_, status_code));
runtime_http_status_code = static_cast<Http::Code>(config_->runtime().snapshot().getInteger(
downstream_cluster_abort_http_status_key_, default_http_status_code));
}

return code;
return runtime_http_status_code;
}

absl::optional<Grpc::Status::GrpcStatus>
FaultFilter::abortGrpcStatus(const Http::RequestHeaderMap& request_headers) {
auto grpc_status = fault_settings_->requestAbort()->grpcStatusCode(
request_headers.get(Filters::Common::Fault::HeaderNames::get().AbortGrpcRequest));

auto default_grpc_status_code = grpc_status.has_value()
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't we return an absl::nullptr from here if grpc_status doesn't have a value? We do a similar thing in the implementation of abortStatus method.

Copy link
Contributor Author

@vijayrajput1 vijayrajput1 Apr 21, 2020

Choose a reason for hiding this comment

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

intention here is to support setting gRPC status even through just runtime config. For example, even if abort fault filter configuration and header doesn't have grpc_status but if the abort_grpc_status_runtime is set we still want to set the grpc_status. Does this make sense ?

Copy link
Contributor

@Augustyniak Augustyniak Apr 22, 2020

Choose a reason for hiding this comment

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

The use case you want to support definitely makes sense. 👍

I'm just a little bit worried that GRPC aborts will end up using proto config in a way that's different from the way other faults use their protos. "Fixed" fault providers - including HTTP status code, response rate limit and delay request - providers, all require proto config values to be present. For the user of the Envoy, it may be a little bit confusing if for GRPC aborts we follow a different convention.

That being said, if runtime-only config is the thing you want to support I'm going to leave it up to more Envoy experienced folks to decide whether it's ok or no to have this fault provider not require full proto config (no GRPC status code required in proto config).

//EDIT
It may fill a little bit off to have a GRPC abort percentage defined but no GRPC abort status code defined in proto config even if fixed GRPC aborts are used.

Copy link
Member

Choose a reason for hiding this comment

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

I agree with @Augustyniak that we should be consistent here. I'm going to defer to @Augustyniak for initial review of this PR and I will do a pass after. :)

? static_cast<uint64_t>(grpc_status.value())
: std::numeric_limits<uint64_t>::max();

auto runtime_grpc_status_code = config_->runtime().snapshot().getInteger(
fault_settings_->abortGrpcStatusRuntime(), default_grpc_status_code);

if (runtime_grpc_status_code == std::numeric_limits<uint64_t>::max()) {
return absl::nullopt;
}

return static_cast<Grpc::Status::GrpcStatus>(runtime_grpc_status_code);
}

void FaultFilter::recordDelaysInjectedStats() {
Expand Down Expand Up @@ -375,19 +408,23 @@ void FaultFilter::postDelayInjection(const Http::RequestHeaderMap& request_heade
resetTimerState();

// Delays can be followed by aborts
const auto abort_code = abortHttpStatus(request_headers);
if (abort_code.has_value()) {
abortWithHTTPStatus(abort_code.value());
absl::optional<Http::Code> http_status;
absl::optional<Grpc::Status::GrpcStatus> grpc_status;
std::tie(http_status, grpc_status) = abortStatus(request_headers);

if (http_status.has_value()) {
abortWithStatus(http_status.value(), grpc_status);
} else {
// Continue request processing.
decoder_callbacks_->continueDecoding();
}
}

void FaultFilter::abortWithHTTPStatus(Http::Code abort_code) {
void FaultFilter::abortWithStatus(Http::Code http_status_code,
absl::optional<Grpc::Status::GrpcStatus> grpc_status_code) {
decoder_callbacks_->streamInfo().setResponseFlag(StreamInfo::ResponseFlag::FaultInjected);
decoder_callbacks_->sendLocalReply(abort_code, "fault filter abort", nullptr, absl::nullopt,
RcDetails::get().FaultAbort);
decoder_callbacks_->sendLocalReply(http_status_code, "fault filter abort", nullptr,
grpc_status_code, RcDetails::get().FaultAbort);
recordAbortsInjectedStats();
}

Expand Down
Loading