-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
http: adding an interface to inform filters of local replies #15172
Changes from 1 commit
ecbba2f
d059f32
0b11bfe
6084a39
b374b19
bd74e50
c077e50
81f63f5
eee1580
9209fa7
3f0e7dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -812,6 +812,18 @@ FilterManager::commonDecodePrefix(ActiveStreamDecoderFilter* filter, | |
return std::next(filter->entry()); | ||
} | ||
|
||
LocalErrorStatus FilterManager::onLocalReply(StreamFilterBase::LocalReplyData& data) { | ||
filter_manager_callbacks_.onLocalReply(data.code_); | ||
|
||
LocalErrorStatus status = LocalErrorStatus::Continue; | ||
for (auto entry : filters_) { | ||
if (entry->onLocalReply(data) == LocalErrorStatus::ContinueAndResetStream) { | ||
status = LocalErrorStatus::ContinueAndResetStream; | ||
} | ||
} | ||
return status; | ||
} | ||
|
||
void FilterManager::sendLocalReply( | ||
bool old_was_grpc_request, Code code, absl::string_view body, | ||
const std::function<void(ResponseHeaderMap& headers)>& modify_headers, | ||
|
@@ -824,7 +836,13 @@ void FilterManager::sendLocalReply( | |
|
||
stream_info_.setResponseCodeDetails(details); | ||
|
||
filter_manager_callbacks_.onLocalReply(code); | ||
StreamFilterBase::LocalReplyData data{code, details}; | ||
if (FilterManager::onLocalReply(data) == LocalErrorStatus::ContinueAndResetStream) { | ||
ENVOY_STREAM_LOG(debug, "Resetting stream due to {}. onLocalReply requested reset.", *this, | ||
details); | ||
Comment on lines
+843
to
+844
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any way we can capture which filter is triggering the reset? Or let the filter that triggers a reset include information? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean we don't really for sendLocalReply logs either, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At least with local replies we can infer it from the response code details, but yea I don't think this is necessary, just a nice to have |
||
filter_manager_callbacks_.resetStream(); | ||
return; | ||
} | ||
|
||
if (!filter_manager_callbacks_.responseHeaders().has_value()) { | ||
// If the response has not started at all, send the response through the filter chain. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -760,6 +760,7 @@ class FilterManager : public ScopeTrackedObject, | |
// Http::FilterChainFactoryCallbacks | ||
void addStreamDecoderFilter(StreamDecoderFilterSharedPtr filter) override { | ||
addStreamDecoderFilterWorker(filter, nullptr, false); | ||
filters_.push_back(filter.get()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we document the order in which filters are given the callback? Seems like the order is first added to last added, regardless of whether it was a decoder or encoder filter. I think people might intuitively expect this to follow the decoder or encoder filter chains, but currently this can interleave between the two. I think with the current impl the order doesn't matter at all, but I can imagine iterations of this feature (like my suggestion of capturing information about which filter is doing the reset) where it starts mattering. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure, added to include. |
||
} | ||
void addStreamDecoderFilter(StreamDecoderFilterSharedPtr filter, | ||
Matcher::MatchTreeSharedPtr<HttpMatchingData> match_tree) override { | ||
|
@@ -776,6 +777,7 @@ class FilterManager : public ScopeTrackedObject, | |
} | ||
void addStreamEncoderFilter(StreamEncoderFilterSharedPtr filter) override { | ||
addStreamEncoderFilterWorker(filter, nullptr, false); | ||
filters_.push_back(filter.get()); | ||
} | ||
void addStreamEncoderFilter(StreamEncoderFilterSharedPtr filter, | ||
Matcher::MatchTreeSharedPtr<HttpMatchingData> match_tree) override { | ||
|
@@ -793,6 +795,8 @@ class FilterManager : public ScopeTrackedObject, | |
void addStreamFilter(StreamFilterSharedPtr filter) override { | ||
addStreamDecoderFilterWorker(filter, nullptr, true); | ||
addStreamEncoderFilterWorker(filter, nullptr, true); | ||
StreamDecoderFilter* decoder_filter = filter.get(); | ||
filters_.push_back(decoder_filter); | ||
} | ||
void addStreamFilter(StreamFilterSharedPtr filter, | ||
Matcher::MatchTreeSharedPtr<HttpMatchingData> match_tree) override { | ||
|
@@ -910,6 +914,13 @@ class FilterManager : public ScopeTrackedObject, | |
*/ | ||
void maybeEndEncode(bool end_stream); | ||
|
||
/** | ||
* Called before local reply is made by the filter manager. | ||
* @param data the data associated with the local reply. | ||
* @param LocalErrorStatus the status from the filter chain. | ||
*/ | ||
LocalErrorStatus onLocalReply(StreamFilterBase::LocalReplyData& data); | ||
|
||
void sendLocalReply(bool is_grpc_request, Code code, absl::string_view body, | ||
const std::function<void(ResponseHeaderMap& headers)>& modify_headers, | ||
const absl::optional<Grpc::Status::GrpcStatus> grpc_status, | ||
|
@@ -1061,6 +1072,7 @@ class FilterManager : public ScopeTrackedObject, | |
|
||
std::list<ActiveStreamDecoderFilterPtr> decoder_filters_; | ||
std::list<ActiveStreamEncoderFilterPtr> encoder_filters_; | ||
std::list<StreamFilterBase*> filters_; | ||
std::list<AccessLog::InstanceSharedPtr> access_log_handlers_; | ||
|
||
// Stores metadata added in the decoding filter that is being processed. Will be cleared before | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#include <string> | ||
|
||
#include "envoy/http/filter.h" | ||
#include "envoy/registry/registry.h" | ||
#include "envoy/server/filter_config.h" | ||
|
||
#include "extensions/filters/http/common/pass_through_filter.h" | ||
|
||
#include "test/extensions/filters/http/common/empty_http_filter_config.h" | ||
|
||
namespace Envoy { | ||
|
||
class OnLocalReplyFilter : public Http::PassThroughFilter { | ||
public: | ||
Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& request_headers, bool) override { | ||
if (request_headers.get(Http::LowerCaseString("reset")).size() != 0) { | ||
reset_ = true; | ||
} | ||
decoder_callbacks_->sendLocalReply(Http::Code::BadRequest, "body", nullptr, absl::nullopt, | ||
"details"); | ||
return Http::FilterHeadersStatus::StopIteration; | ||
} | ||
|
||
Http::LocalErrorStatus onLocalReply(LocalReplyData&) override { | ||
if (reset_) { | ||
return Http::LocalErrorStatus::ContinueAndResetStream; | ||
} | ||
return Http::LocalErrorStatus::Continue; | ||
} | ||
|
||
bool reset_{}; | ||
}; | ||
|
||
class OnLocalReplyFilterConfig : public Extensions::HttpFilters::Common::EmptyHttpFilterConfig { | ||
public: | ||
OnLocalReplyFilterConfig() : EmptyHttpFilterConfig("on-local-reply-filter") {} | ||
Http::FilterFactoryCb createFilter(const std::string&, | ||
Server::Configuration::FactoryContext&) override { | ||
return [](Http::FilterChainFactoryCallbacks& callbacks) -> void { | ||
callbacks.addStreamFilter(std::make_shared<::Envoy::OnLocalReplyFilter>()); | ||
}; | ||
} | ||
}; | ||
|
||
// perform static registration | ||
static Registry::RegisterFactory<OnLocalReplyFilterConfig, | ||
Server::Configuration::NamedHttpFilterConfigFactory> | ||
register_; | ||
} // namespace Envoy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have some way of indicating to filters that the local reply is going to be reset? I can imagine filters wanting to do some mutation of the local reply in some cases, but it doesn't make sense for them to do this if a previous filter has triggered a reset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
they can't mutate the local reply here, only from the actual sendlocalReply, but can't hurt to pass on that info