Line data Source code
1 : #pragma once 2 : 3 : #include "envoy/http/filter.h" 4 : #include "envoy/matcher/matcher.h" 5 : #include "envoy/server/factory_context.h" 6 : #include "envoy/type/matcher/v3/http_inputs.pb.h" 7 : #include "envoy/type/matcher/v3/http_inputs.pb.validate.h" 8 : 9 : #include "source/common/http/header_utility.h" 10 : #include "source/common/http/utility.h" 11 : #include "source/extensions/filters/common/expr/evaluator.h" 12 : 13 : #include "xds/type/matcher/v3/http_inputs.pb.h" 14 : 15 : namespace Envoy { 16 : namespace Extensions { 17 : namespace Matching { 18 : namespace Http { 19 : namespace CelInput { 20 : 21 : using ::Envoy::Http::RequestHeaderMapOptConstRef; 22 : using ::Envoy::Http::ResponseHeaderMapOptConstRef; 23 : using ::Envoy::Http::ResponseTrailerMapOptConstRef; 24 : 25 : using BaseActivationPtr = std::unique_ptr<google::api::expr::runtime::BaseActivation>; 26 : 27 : // CEL matcher specific matching data 28 : class CelMatchData : public ::Envoy::Matcher::CustomMatchData { 29 : public: 30 0 : explicit CelMatchData(BaseActivationPtr activation) : activation_(std::move(activation)) {} 31 : BaseActivationPtr activation_; 32 : }; 33 : 34 : class HttpCelDataInput : public Matcher::DataInput<Envoy::Http::HttpMatchingData> { 35 : public: 36 0 : HttpCelDataInput() = default; 37 0 : Matcher::DataInputGetResult get(const Envoy::Http::HttpMatchingData& data) const override { 38 0 : RequestHeaderMapOptConstRef maybe_request_headers = data.requestHeaders(); 39 0 : ResponseHeaderMapOptConstRef maybe_response_headers = data.responseHeaders(); 40 0 : ResponseTrailerMapOptConstRef maybe_response_trailers = data.responseTrailers(); 41 : 42 : // CEL library supports mixed matching of request/response attributes(e.g., headers, trailers) 43 : // and attributes from stream info. 44 0 : std::unique_ptr<google::api::expr::runtime::BaseActivation> activation = 45 0 : Extensions::Filters::Common::Expr::createActivation( 46 0 : nullptr, // TODO: pass local_info to CEL activation. 47 0 : data.streamInfo(), maybe_request_headers.ptr(), maybe_response_headers.ptr(), 48 0 : maybe_response_trailers.ptr()); 49 : 50 0 : return {Matcher::DataInputGetResult::DataAvailability::AllDataAvailable, 51 0 : std::make_unique<CelMatchData>(std::move(activation))}; 52 0 : } 53 : 54 0 : absl::string_view dataInputType() const override { return "cel_data_input"; } 55 : }; 56 : 57 : class HttpCelDataInputFactory : public Matcher::DataInputFactory<Envoy::Http::HttpMatchingData> { 58 : public: 59 3 : HttpCelDataInputFactory() = default; 60 39 : std::string name() const override { return "envoy.matching.inputs.cel_data_input"; } 61 : 62 : Matcher::DataInputFactoryCb<Envoy::Http::HttpMatchingData> 63 0 : createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override { 64 0 : return [] { return std::make_unique<HttpCelDataInput>(); }; 65 0 : } 66 : 67 1 : ProtobufTypes::MessagePtr createEmptyConfigProto() override { 68 1 : return std::make_unique<xds::type::matcher::v3::HttpAttributesCelMatchInput>(); 69 1 : } 70 : }; 71 : 72 : DECLARE_FACTORY(HttpCelDataInputFactory); 73 : 74 : } // namespace CelInput 75 : } // namespace Http 76 : } // namespace Matching 77 : } // namespace Extensions 78 : } // namespace Envoy