Skip to content

Commit

Permalink
http: support creating filters with match tree (#14430)
Browse files Browse the repository at this point in the history
Adds support for wrapping a HTTP filter with an ExtensionWithMatcher proto to create the filters with an associated match tree.

Under the hood this makes use of a wrapper filter factory that manages creating the match tree and adding it to the FM
alongside the associated filter.

Also includes some code to register factories for input/actions, allowing them to be referenced in the proto configuration.


Signed-off-by: Snow Pettersen <snowp@lyft.com>
  • Loading branch information
Snow Pettersen authored Jan 12, 2021
1 parent c2522c6 commit dcf575a
Show file tree
Hide file tree
Showing 21 changed files with 677 additions and 9 deletions.
35 changes: 35 additions & 0 deletions api/envoy/type/matcher/v3/http_inputs.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
syntax = "proto3";

package envoy.type.matcher.v3;

import "udpa/annotations/migrate.proto";
import "udpa/annotations/status.proto";
import "udpa/annotations/versioning.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.type.matcher.v3";
option java_outer_classname = "HttpInputsProto";
option java_multiple_files = true;
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Common HTTP Inputs]

// Match input indicates that matching should be done on a specific request header.
// The resulting input string will be all headers for the given key joined by a comma,
// e.g. if the request contains two 'foo' headers with value 'bar' and 'baz', the input
// string will be 'bar,baz'.
// [#comment:TODO(snowp): Link to unified matching docs.]
message HttpRequestHeaderMatchInput {
// The request header to match on.
string header_name = 1;
}

// Match input indicating that matching should be done on a specific response header.
// The resulting input string will be all headers for the given key joined by a comma,
// e.g. if the response contains two 'foo' headers with value 'bar' and 'baz', the input
// string will be 'bar,baz'.
// [#comment:TODO(snowp): Link to unified matching docs.]
message HttpResponseHeaderMatchInput {
// The response header to match on.
string header_name = 1;
}
40 changes: 40 additions & 0 deletions api/envoy/type/matcher/v4alpha/http_inputs.proto

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

1 change: 1 addition & 0 deletions docs/root/api-v3/types/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ Types
../type/matcher/v3/string.proto
../type/matcher/v3/struct.proto
../type/matcher/v3/value.proto
../type/matcher/v3/http_inputs.proto
../type/metadata/v3/metadata.proto
../type/tracing/v3/custom_tag.proto
35 changes: 35 additions & 0 deletions generated_api_shadow/envoy/type/matcher/v3/http_inputs.proto

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

40 changes: 40 additions & 0 deletions generated_api_shadow/envoy/type/matcher/v4alpha/http_inputs.proto

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

2 changes: 2 additions & 0 deletions include/envoy/http/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,8 @@ using StreamFilterSharedPtr = std::shared_ptr<StreamFilter>;

class HttpMatchingData {
public:
static absl::string_view name() { return "http"; }

virtual ~HttpMatchingData() = default;

virtual RequestHeaderMapOptConstRef requestHeaders() const PURE;
Expand Down
1 change: 1 addition & 0 deletions include/envoy/matcher/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ envoy_cc_library(
],
deps = [
"//include/envoy/config:typed_config_interface",
"//include/envoy/protobuf:message_validator_interface",
"@envoy_api//envoy/config/common/matcher/v3:pkg_cc_proto",
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
],
Expand Down
5 changes: 4 additions & 1 deletion include/envoy/matcher/matcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "envoy/config/common/matcher/v3/matcher.pb.h"
#include "envoy/config/core/v3/extension.pb.h"
#include "envoy/config/typed_config.h"
#include "envoy/protobuf/message_validator.h"

#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
Expand Down Expand Up @@ -209,7 +210,9 @@ template <class DataType> class DataInputFactory : public Config::TypedFactory {
/**
* Creates a DataInput from the provided config.
*/
virtual DataInputPtr<DataType> createDataInput(const Protobuf::Message& config) PURE;
virtual DataInputPtr<DataType>
createDataInput(const Protobuf::Message& config,
ProtobufMessage::ValidationVisitor& validation_visitor) PURE;

/**
* The category of this factory depends on the DataType, so we require a name() function to exist
Expand Down
3 changes: 3 additions & 0 deletions source/common/http/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ envoy_cc_library(
"//source/common/local_reply:local_reply_lib",
"//source/common/matcher:matcher_lib",
"@envoy_api//envoy/extensions/filters/common/matcher/action/v3:pkg_cc_proto",
"@envoy_api//envoy/extensions/filters/network/http_connection_manager/v3:pkg_cc_proto",
"@envoy_api//envoy/type/matcher/v3:pkg_cc_proto",
],
)

Expand Down Expand Up @@ -247,6 +249,7 @@ envoy_cc_library(
"//source/common/http/http2:codec_lib",
"//source/common/http/http3:quic_codec_factory_lib",
"//source/common/http/http3:well_known_names",
"//source/common/http/match_wrapper:config",
"//source/common/network:utility_lib",
"//source/common/router:config_lib",
"//source/common/router:scoped_rds_lib",
Expand Down
2 changes: 2 additions & 0 deletions source/common/http/filter_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace Envoy {
namespace Http {

namespace {
REGISTER_FACTORY(HttpRequestHeadersDataInputFactory, Matcher::DataInputFactory<HttpMatchingData>);
REGISTER_FACTORY(SkipActionFactory, Matcher::ActionFactory);

template <class T> using FilterList = std::list<std::unique_ptr<T>>;

Expand Down
52 changes: 52 additions & 0 deletions source/common/http/filter_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@

#include "envoy/common/optref.h"
#include "envoy/extensions/filters/common/matcher/action/v3/skip_action.pb.h"
#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h"
#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.validate.h"
#include "envoy/http/filter.h"
#include "envoy/http/header_map.h"
#include "envoy/matcher/matcher.h"
#include "envoy/network/socket.h"
#include "envoy/protobuf/message_validator.h"
#include "envoy/type/matcher/v3/http_inputs.pb.validate.h"

#include "common/buffer/watermark_buffer.h"
#include "common/common/dump_state_utils.h"
Expand All @@ -18,6 +22,7 @@
#include "common/http/headers.h"
#include "common/local_reply/local_reply.h"
#include "common/matcher/matcher.h"
#include "common/protobuf/utility.h"

namespace Envoy {
namespace Http {
Expand Down Expand Up @@ -97,6 +102,36 @@ class HttpRequestHeadersDataInput : public HttpHeadersDataInputBase<RequestHeade
}
};

template <class DataInputType, class ProtoType>
class HttpHeadersDataInputFactoryBase : public Matcher::DataInputFactory<HttpMatchingData> {
public:
explicit HttpHeadersDataInputFactoryBase(const std::string& name) : name_(name) {}

std::string name() const override { return name_; }

Matcher::DataInputPtr<HttpMatchingData>
createDataInput(const Protobuf::Message& config,
ProtobufMessage::ValidationVisitor& validation_visitor) override {
const auto& typed_config =
MessageUtil::downcastAndValidate<const ProtoType&>(config, validation_visitor);

return std::make_unique<DataInputType>(typed_config.header_name());
};
ProtobufTypes::MessagePtr createEmptyConfigProto() override {
return std::make_unique<ProtoType>();
}

private:
const std::string name_;
};

class HttpRequestHeadersDataInputFactory
: public HttpHeadersDataInputFactoryBase<
HttpRequestHeadersDataInput, envoy::type::matcher::v3::HttpRequestHeaderMatchInput> {
public:
HttpRequestHeadersDataInputFactory() : HttpHeadersDataInputFactoryBase("request-headers") {}
};

class HttpResponseHeadersDataInput : public HttpHeadersDataInputBase<ResponseHeaderMap> {
public:
explicit HttpResponseHeadersDataInput(const std::string& name) : HttpHeadersDataInputBase(name) {}
Expand All @@ -107,9 +142,26 @@ class HttpResponseHeadersDataInput : public HttpHeadersDataInputBase<ResponseHea
}
};

class HttpResponseHeadersDataInputFactory
: public HttpHeadersDataInputFactoryBase<
HttpResponseHeadersDataInput, envoy::type::matcher::v3::HttpResponseHeaderMatchInput> {
public:
HttpResponseHeadersDataInputFactory() : HttpHeadersDataInputFactoryBase("response-headers") {}
};

class SkipAction : public Matcher::ActionBase<
envoy::extensions::filters::common::matcher::action::v3::SkipFilter> {};

class SkipActionFactory : public Matcher::ActionFactory {
public:
std::string name() const override { return "skip"; }
Matcher::ActionFactoryCb createActionFactoryCb(const Protobuf::Message&) override {
return []() { return std::make_unique<SkipAction>(); };
}
ProtobufTypes::MessagePtr createEmptyConfigProto() override {
return std::make_unique<envoy::extensions::filters::common::matcher::action::v3::SkipFilter>();
}
};
/**
* Base class wrapper for both stream encoder and decoder filters.
*
Expand Down
23 changes: 23 additions & 0 deletions source/common/http/match_wrapper/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
load(
"//bazel:envoy_build_system.bzl",
"envoy_cc_library",
"envoy_package",
)

licenses(["notice"]) # Apache 2

envoy_package()

envoy_cc_library(
name = "config",
srcs = ["config.cc"],
hdrs = ["config.h"],
deps = [
"//include/envoy/registry",
"//include/envoy/server:filter_config_interface",
"//source/common/matcher:matcher_lib",
"//source/extensions/filters/http:well_known_names",
"//source/extensions/filters/http/common:factory_base_lib",
"@envoy_api//envoy/extensions/common/matching/v3:pkg_cc_proto",
],
)
Loading

0 comments on commit dcf575a

Please sign in to comment.