Line data Source code
1 : #pragma once 2 : 3 : #include <memory> 4 : 5 : #include "envoy/extensions/common/matching/v3/extension_matcher.pb.validate.h" 6 : #include "envoy/extensions/filters/common/matcher/action/v3/skip_action.pb.h" 7 : #include "envoy/matcher/matcher.h" 8 : #include "envoy/server/filter_config.h" 9 : 10 : #include "source/common/http/matching/data_impl.h" 11 : #include "source/common/matcher/matcher.h" 12 : #include "source/extensions/filters/http/common/factory_base.h" 13 : 14 : namespace Envoy { 15 : namespace Common { 16 : namespace Http { 17 : namespace MatchDelegate { 18 : 19 : class SkipAction : public Matcher::ActionBase< 20 : envoy::extensions::filters::common::matcher::action::v3::SkipFilter> {}; 21 : 22 : class DelegatingStreamFilter : public Logger::Loggable<Logger::Id::http>, 23 : public Envoy::Http::StreamFilter { 24 : public: 25 : using MatchDataUpdateFunc = std::function<void(Envoy::Http::Matching::HttpMatchingDataImpl&)>; 26 : 27 : class FilterMatchState { 28 : public: 29 : FilterMatchState(Matcher::MatchTreeSharedPtr<Envoy::Http::HttpMatchingData> match_tree) 30 0 : : match_tree_(std::move(match_tree)), has_match_tree_(match_tree_ != nullptr) {} 31 : 32 : void evaluateMatchTree(MatchDataUpdateFunc data_update_func); 33 0 : bool skipFilter() const { return skip_filter_; } 34 0 : void onStreamInfo(const StreamInfo::StreamInfo& stream_info) { 35 0 : if (matching_data_ == nullptr) { 36 0 : matching_data_ = std::make_shared<Envoy::Http::Matching::HttpMatchingDataImpl>(stream_info); 37 0 : } 38 0 : } 39 : 40 : // The matcher from the per route config, if available, will override the matcher from the 41 : // filter config. 42 0 : void setMatchTree(Matcher::MatchTreeSharedPtr<Envoy::Http::HttpMatchingData> match_tree) { 43 0 : match_tree_ = std::move(match_tree); 44 0 : has_match_tree_ = match_tree_ != nullptr; 45 0 : } 46 : 47 0 : void setBaseFilter(Envoy::Http::StreamFilterBase* base_filter) { base_filter_ = base_filter; } 48 : 49 : private: 50 : Matcher::MatchTreeSharedPtr<Envoy::Http::HttpMatchingData> match_tree_; 51 : bool has_match_tree_{}; 52 : Envoy::Http::StreamFilterBase* base_filter_{}; 53 : 54 : Envoy::Http::Matching::HttpMatchingDataImplSharedPtr matching_data_; 55 : bool match_tree_evaluated_{}; 56 : bool skip_filter_{}; 57 : }; 58 : 59 : DelegatingStreamFilter(Matcher::MatchTreeSharedPtr<Envoy::Http::HttpMatchingData> match_tree, 60 : Envoy::Http::StreamDecoderFilterSharedPtr decoder_filter, 61 : Envoy::Http::StreamEncoderFilterSharedPtr encoder_filter); 62 : 63 : // Envoy::Http::StreamFilterBase 64 0 : void onStreamComplete() override { base_filter_->onStreamComplete(); } 65 0 : void onDestroy() override { base_filter_->onDestroy(); } 66 0 : void onMatchCallback(const Matcher::Action& action) override { 67 0 : base_filter_->onMatchCallback(action); 68 0 : } 69 0 : Envoy::Http::LocalErrorStatus onLocalReply(const LocalReplyData& data) override { 70 0 : return base_filter_->onLocalReply(data); 71 0 : } 72 : 73 : // Envoy::Http::StreamDecoderFilter 74 : Envoy::Http::FilterHeadersStatus decodeHeaders(Envoy::Http::RequestHeaderMap& headers, 75 : bool end_stream) override; 76 : Envoy::Http::FilterDataStatus decodeData(Buffer::Instance& data, bool end_stream) override; 77 : Envoy::Http::FilterTrailersStatus 78 : decodeTrailers(Envoy::Http::RequestTrailerMap& trailers) override; 79 : 80 : Envoy::Http::FilterMetadataStatus decodeMetadata(Envoy::Http::MetadataMap& metadata_map) override; 81 : void decodeComplete() override; 82 : void setDecoderFilterCallbacks(Envoy::Http::StreamDecoderFilterCallbacks& callbacks) override; 83 : 84 : // Envoy::Http::StreamEncoderFilter 85 : Envoy::Http::Filter1xxHeadersStatus 86 : encode1xxHeaders(Envoy::Http::ResponseHeaderMap& headers) override; 87 : Envoy::Http::FilterHeadersStatus encodeHeaders(Envoy::Http::ResponseHeaderMap& headers, 88 : bool end_stream) override; 89 : Envoy::Http::FilterDataStatus encodeData(Buffer::Instance& data, bool end_stream) override; 90 : Envoy::Http::FilterTrailersStatus 91 : encodeTrailers(Envoy::Http::ResponseTrailerMap& trailers) override; 92 : Envoy::Http::FilterMetadataStatus encodeMetadata(Envoy::Http::MetadataMap& metadata_map) override; 93 : void encodeComplete() override; 94 : void setEncoderFilterCallbacks(Envoy::Http::StreamEncoderFilterCallbacks& callbacks) override; 95 : 96 : private: 97 : FilterMatchState match_state_; 98 : 99 : Envoy::Http::StreamDecoderFilterSharedPtr decoder_filter_; 100 : Envoy::Http::StreamEncoderFilterSharedPtr encoder_filter_; 101 : Envoy::Http::StreamDecoderFilterCallbacks* decoder_callbacks_{}; 102 : Envoy::Http::StreamEncoderFilterCallbacks* encoder_callbacks_{}; 103 : Envoy::Http::StreamFilterBase* base_filter_{}; 104 : }; 105 : 106 : class MatchDelegateConfig 107 : : public Extensions::HttpFilters::Common::FactoryBase< 108 : envoy::extensions::common::matching::v3::ExtensionWithMatcher, 109 : envoy::extensions::common::matching::v3::ExtensionWithMatcherPerRoute> { 110 : public: 111 : // TODO(wbpcode): move this filter to 'source/extensions/filters/http'. 112 56 : MatchDelegateConfig() : FactoryBase("envoy.filters.http.match_delegate") {} 113 : 114 : private: 115 : Envoy::Http::FilterFactoryCb createFilterFactoryFromProtoTyped( 116 : const envoy::extensions::common::matching::v3::ExtensionWithMatcher& proto_config, 117 : const std::string&, Server::Configuration::FactoryContext& context) override; 118 : 119 : Router::RouteSpecificFilterConfigConstSharedPtr createRouteSpecificFilterConfigTyped( 120 : const envoy::extensions::common::matching::v3::ExtensionWithMatcherPerRoute& proto_config, 121 : Server::Configuration::ServerFactoryContext& context, 122 : ProtobufMessage::ValidationVisitor& validation) override; 123 : }; 124 : 125 : class FilterConfigPerRoute : public Router::RouteSpecificFilterConfig { 126 : public: 127 : FilterConfigPerRoute( 128 : const envoy::extensions::common::matching::v3::ExtensionWithMatcherPerRoute& proto_config, 129 : Server::Configuration::ServerFactoryContext& server_context) 130 0 : : match_tree_(createFilterMatchTree(proto_config, server_context)) {} 131 : 132 0 : const Matcher::MatchTreeSharedPtr<Envoy::Http::HttpMatchingData>& matchTree() const { 133 0 : return match_tree_; 134 0 : } 135 : 136 : private: 137 : Matcher::MatchTreeSharedPtr<Envoy::Http::HttpMatchingData> createFilterMatchTree( 138 : const envoy::extensions::common::matching::v3::ExtensionWithMatcherPerRoute& proto_config, 139 : Server::Configuration::ServerFactoryContext& server_context); 140 : Matcher::MatchTreeSharedPtr<Envoy::Http::HttpMatchingData> match_tree_; 141 : }; 142 : 143 : DECLARE_FACTORY(MatchDelegateConfig); 144 : 145 : namespace Factory { 146 : DECLARE_FACTORY(SkipActionFactory); 147 : } // namespace Factory 148 : 149 : } // namespace MatchDelegate 150 : } // namespace Http 151 : } // namespace Common 152 : } // namespace Envoy