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 StreamActivationPtr = std::unique_ptr<Filters::Common::Expr::StreamActivation>;
26

            
27
// CEL matcher specific matching data
28
class CelMatchData : public ::Envoy::Matcher::CustomMatchData {
29
public:
30
107
  explicit CelMatchData(StreamActivationPtr activation) : activation_(std::move(activation)) {}
31
36
  bool needs_response() const { return activation_->needs_response_path_data(); }
32
9
  bool has_response_data() const { return activation_->has_response_data(); }
33
  StreamActivationPtr activation_;
34
};
35

            
36
class HttpCelDataInput : public Matcher::DataInput<Envoy::Http::HttpMatchingData> {
37
public:
38
115
  HttpCelDataInput() = default;
39
107
  Matcher::DataInputGetResult get(const Envoy::Http::HttpMatchingData& data) const override {
40
107
    RequestHeaderMapOptConstRef maybe_request_headers = data.requestHeaders();
41
107
    ResponseHeaderMapOptConstRef maybe_response_headers = data.responseHeaders();
42
107
    ResponseTrailerMapOptConstRef maybe_response_trailers = data.responseTrailers();
43

            
44
    // CEL library supports mixed matching of request/response attributes(e.g., headers, trailers)
45
    // and attributes from stream info.
46
107
    StreamActivationPtr activation = Extensions::Filters::Common::Expr::createActivation(
47
107
        nullptr, // TODO: pass local_info to CEL activation.
48
107
        data.streamInfo(), maybe_request_headers.ptr(), maybe_response_headers.ptr(),
49
107
        maybe_response_trailers.ptr());
50

            
51
107
    return Matcher::DataInputGetResult::CreateCustom(
52
107
        std::make_shared<CelMatchData>(std::move(activation)));
53
107
  }
54

            
55
114
  absl::string_view dataInputType() const override { return "cel_data_input"; }
56
};
57

            
58
class HttpCelDataInputFactory : public Matcher::DataInputFactory<Envoy::Http::HttpMatchingData> {
59
public:
60
23
  HttpCelDataInputFactory() = default;
61
345
  std::string name() const override { return "envoy.matching.inputs.cel_data_input"; }
62

            
63
  Matcher::DataInputFactoryCb<Envoy::Http::HttpMatchingData>
64
116
  createDataInputFactoryCb(const Protobuf::Message&, ProtobufMessage::ValidationVisitor&) override {
65
116
    return [] { return std::make_unique<HttpCelDataInput>(); };
66
116
  }
67

            
68
136
  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
69
136
    return std::make_unique<xds::type::matcher::v3::HttpAttributesCelMatchInput>();
70
136
  }
71
};
72

            
73
DECLARE_FACTORY(HttpCelDataInputFactory);
74

            
75
} // namespace CelInput
76
} // namespace Http
77
} // namespace Matching
78
} // namespace Extensions
79
} // namespace Envoy