Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 13 additions & 4 deletions api/envoy/data/tap/v2alpha/http.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,18 @@ import "envoy/api/v2/core/base.proto";

// A fully buffered HTTP trace message.
message HttpBufferedTrace {
// Request headers.
repeated api.v2.core.HeaderValue request_headers = 2;
// HTTP message wrapper.
message Message {
// Message headers.
repeated api.v2.core.HeaderValue headers = 1;

// Response headers.
repeated api.v2.core.HeaderValue response_headers = 3;
// Message trailers.
repeated api.v2.core.HeaderValue trailers = 2;
}

// Request message.
Message request = 1;

// Response message.
Message response = 2;
}
26 changes: 13 additions & 13 deletions api/envoy/service/tap/v2alpha/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,23 @@ message MatchPredicate {
// The match configuration will always match.
bool any_match = 4 [(validate.rules).bool.const = true];

// HTTP request match configuration.
HttpRequestMatch http_request_match = 5;
// HTTP request headers match configuration.
HttpHeadersMatch http_request_headers_match = 5;
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 organize this a bit, just like how BufferedTrace organized? i.e.

message HttpMessageMatch {
  HttpHeadersMatch headers_match;
  HttpTrailersMatch trailers_match;
}

?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is how I had this originally, but IMO we don't want this, because it makes it much more confusing on how to apply and/or logic.


// HTTP response match configuration.
HttpResponseMatch http_response_match = 6;
}
}
// HTTP request trailers match configuration.
HttpHeadersMatch http_request_trailers_match = 6;

// HTTP request match configuration.
message HttpRequestMatch {
// HTTP request headers to match.
repeated api.v2.route.HeaderMatcher headers = 1;
// HTTP response headers match configuration.
HttpHeadersMatch http_response_headers_match = 7;

// HTTP response trailers match configuration.
HttpHeadersMatch http_response_trailers_match = 8;
}
}

// HTTP response match configuration.
message HttpResponseMatch {
// HTTP response headers to match.
// HTTP headers match configuration.
message HttpHeadersMatch {
// HTTP headers to match.
repeated api.v2.route.HeaderMatcher headers = 1;
}

Expand Down
8 changes: 4 additions & 4 deletions docs/root/configuration/http_filters/tap_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ An example POST body:
match_config:
and_match:
rules:
- http_request_match:
- http_request_headers_match:
headers:
- name: foo
exact_match: bar
- http_response_match:
- http_response_headers_match:
headers:
- name: bar
exact_match: baz
Expand All @@ -90,11 +90,11 @@ Another example POST body:
match_config:
or_match:
rules:
- http_request_match:
- http_request_headers_match:
headers:
- name: foo
exact_match: bar
- http_response_match:
- http_response_headers_match:
headers:
- name: bar
exact_match: baz
Expand Down
1 change: 1 addition & 0 deletions source/common/router/router.cc
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ Http::FilterDataStatus Filter::decodeData(Buffer::Instance& data, bool end_strea
}

Http::FilterTrailersStatus Filter::decodeTrailers(Http::HeaderMap& trailers) {
ENVOY_STREAM_LOG(debug, "router decoding trailers:\n{}", *callbacks_, trailers);
downstream_trailers_ = &trailers;
upstream_request_->encodeTrailers(trailers);
onRequestComplete();
Expand Down
99 changes: 31 additions & 68 deletions source/extensions/common/tap/tap_matcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,21 @@ void buildMatcher(const envoy::service::tap::v2alpha::MatchPredicate& match_conf
case envoy::service::tap::v2alpha::MatchPredicate::kAnyMatch:
new_matcher = std::make_unique<AnyMatcher>(matchers);
break;
case envoy::service::tap::v2alpha::MatchPredicate::kHttpRequestMatch:
new_matcher = std::make_unique<HttpRequestMatcher>(match_config.http_request_match(), matchers);
case envoy::service::tap::v2alpha::MatchPredicate::kHttpRequestHeadersMatch:
new_matcher = std::make_unique<HttpRequestHeadersMatcher>(
match_config.http_request_headers_match(), matchers);
break;
case envoy::service::tap::v2alpha::MatchPredicate::kHttpResponseMatch:
new_matcher =
std::make_unique<HttpResponseMatcher>(match_config.http_response_match(), matchers);
case envoy::service::tap::v2alpha::MatchPredicate::kHttpRequestTrailersMatch:
new_matcher = std::make_unique<HttpRequestTrailersMatcher>(
match_config.http_request_trailers_match(), matchers);
break;
case envoy::service::tap::v2alpha::MatchPredicate::kHttpResponseHeadersMatch:
new_matcher = std::make_unique<HttpResponseHeadersMatcher>(
match_config.http_response_headers_match(), matchers);
break;
case envoy::service::tap::v2alpha::MatchPredicate::kHttpResponseTrailersMatch:
new_matcher = std::make_unique<HttpResponseTrailersMatcher>(
match_config.http_response_trailers_match(), matchers);
break;
default:
NOT_REACHED_GCOVR_EXCL_LINE;
Expand All @@ -50,14 +59,19 @@ void buildMatcher(const envoy::service::tap::v2alpha::MatchPredicate& match_conf
SetLogicMatcher::SetLogicMatcher(
const envoy::service::tap::v2alpha::MatchPredicate::MatchSet& configs,
std::vector<MatcherPtr>& matchers, Type type)
: Matcher(matchers), matchers_(matchers), type_(type) {
: LogicMatcherBase(matchers), matchers_(matchers), type_(type) {
for (const auto& config : configs.rules()) {
indexes_.push_back(matchers_.size());
buildMatcher(config, matchers_);
}
}

bool SetLogicMatcher::updateLocalStatus(std::vector<bool>& statuses) const {
bool SetLogicMatcher::updateLocalStatus(std::vector<bool>& statuses,
const UpdateFunctor& functor) const {
for (size_t index : indexes_) {
statuses[index] = functor(*matchers_[index], statuses);
}

auto predicate = [&statuses](size_t index) { return statuses[index]; };
if (type_ == Type::And) {
statuses[my_index_] = std::all_of(indexes_.begin(), indexes_.end(), predicate);
Expand All @@ -69,81 +83,30 @@ bool SetLogicMatcher::updateLocalStatus(std::vector<bool>& statuses) const {
return statuses[my_index_];
}

bool SetLogicMatcher::onNewStream(std::vector<bool>& statuses) const {
for (size_t index : indexes_) {
statuses[index] = matchers_[index]->onNewStream(statuses);
}

return updateLocalStatus(statuses);
}

bool SetLogicMatcher::onHttpRequestHeaders(const Http::HeaderMap& request_headers,
std::vector<bool>& statuses) const {
for (size_t index : indexes_) {
statuses[index] = matchers_[index]->onHttpRequestHeaders(request_headers, statuses);
}

return updateLocalStatus(statuses);
}

bool SetLogicMatcher::onHttpResponseHeaders(const Http::HeaderMap& response_headers,
std::vector<bool>& statuses) const {
for (size_t index : indexes_) {
statuses[index] = matchers_[index]->onHttpResponseHeaders(response_headers, statuses);
}

return updateLocalStatus(statuses);
}

NotMatcher::NotMatcher(const envoy::service::tap::v2alpha::MatchPredicate& config,
std::vector<MatcherPtr>& matchers)
: Matcher(matchers), matchers_(matchers), not_index_(matchers.size()) {
: LogicMatcherBase(matchers), matchers_(matchers), not_index_(matchers.size()) {
buildMatcher(config, matchers);
}

bool NotMatcher::onNewStream(std::vector<bool>& statuses) const {
statuses[my_index_] = !matchers_[not_index_]->onNewStream(statuses);
return statuses[my_index_];
}

bool NotMatcher::onHttpRequestHeaders(const Http::HeaderMap& request_headers,
std::vector<bool>& statuses) const {
statuses[my_index_] = !matchers_[not_index_]->onHttpRequestHeaders(request_headers, statuses);
return statuses[my_index_];
}

bool NotMatcher::onHttpResponseHeaders(const Http::HeaderMap& response_headers,
std::vector<bool>& statuses) const {
statuses[my_index_] = !matchers_[not_index_]->onHttpResponseHeaders(response_headers, statuses);
return statuses[my_index_];
}

HttpRequestMatcher::HttpRequestMatcher(const envoy::service::tap::v2alpha::HttpRequestMatch& config,
const std::vector<MatcherPtr>& matchers)
: Matcher(matchers) {
for (const auto& header_match : config.headers()) {
headers_to_match_.emplace_back(header_match);
}
}

bool HttpRequestMatcher::onHttpRequestHeaders(const Http::HeaderMap& request_headers,
std::vector<bool>& statuses) const {
statuses[my_index_] = Http::HeaderUtility::matchHeaders(request_headers, headers_to_match_);
bool NotMatcher::updateLocalStatus(std::vector<bool>& statuses,
const UpdateFunctor& functor) const {
statuses[my_index_] = !functor(*matchers_[not_index_], statuses);
return statuses[my_index_];
}

HttpResponseMatcher::HttpResponseMatcher(
const envoy::service::tap::v2alpha::HttpResponseMatch& config,
HttpHeaderMatcherBase::HttpHeaderMatcherBase(
const envoy::service::tap::v2alpha::HttpHeadersMatch& config,
const std::vector<MatcherPtr>& matchers)
: Matcher(matchers) {
: SimpleMatcher(matchers) {
for (const auto& header_match : config.headers()) {
headers_to_match_.emplace_back(header_match);
}
}

bool HttpResponseMatcher::onHttpResponseHeaders(const Http::HeaderMap& response_headers,
std::vector<bool>& statuses) const {
statuses[my_index_] = Http::HeaderUtility::matchHeaders(response_headers, headers_to_match_);
bool HttpHeaderMatcherBase::matchHeaders(const Http::HeaderMap& headers,
std::vector<bool>& statuses) const {
statuses[my_index_] = Http::HeaderUtility::matchHeaders(headers, headers_to_match_);
return statuses[my_index_];
}

Expand Down
Loading