1
#pragma once
2

            
3
#include "envoy/extensions/matching/common_inputs/network/v3/network_inputs.pb.h"
4
#include "envoy/extensions/matching/common_inputs/network/v3/network_inputs.pb.validate.h"
5
#include "envoy/http/filter.h"
6
#include "envoy/matcher/matcher.h"
7

            
8
#include "source/common/config/metadata.h"
9

            
10
namespace Envoy {
11
namespace Extensions {
12
namespace Matching {
13
namespace Http {
14
namespace MetadataInput {
15

            
16
class MetadataMatchData : public ::Envoy::Matcher::CustomMatchData {
17
public:
18
27
  explicit MetadataMatchData(const Protobuf::Value& value) : value_(value) {}
19
  const Protobuf::Value& value_;
20
};
21

            
22
template <class MatchingDataType>
23
class DynamicMetadataInput : public Matcher::DataInput<MatchingDataType> {
24
public:
25
  DynamicMetadataInput(
26
      const envoy::extensions::matching::common_inputs::network::v3::DynamicMetadataInput&
27
          input_config)
28
11
      : filter_(input_config.filter()), path_(initializePath(input_config.path())) {}
29

            
30
27
  Matcher::DataInputGetResult get(const MatchingDataType& data) const override {
31
27
    return Matcher::DataInputGetResult::CreateCustom(std::make_shared<MetadataMatchData>(
32
27
        Envoy::Config::Metadata::metadataValue(&data.metadata(), filter_, path_)));
33
27
  }
34

            
35
private:
36
  static std::vector<std::string> initializePath(
37
      const Protobuf::RepeatedPtrField<envoy::extensions::matching::common_inputs::network::v3::
38
11
                                           DynamicMetadataInput::PathSegment>& segments) {
39
11
    std::vector<std::string> path;
40
11
    for (const auto& seg : segments) {
41
11
      path.push_back(seg.key());
42
11
    }
43
11
    return path;
44
11
  }
45

            
46
  const std::string filter_;
47
  const std::vector<std::string> path_;
48
};
49

            
50
template <class MatchingDataType>
51
class DynamicMetadataInputBaseFactory : public Matcher::DataInputFactory<MatchingDataType> {
52
public:
53
324
  std::string name() const override { return "envoy.matching.inputs.dynamic_metadata"; }
54

            
55
  Matcher::DataInputFactoryCb<MatchingDataType>
56
  createDataInputFactoryCb(const Protobuf::Message& message,
57
11
                           ProtobufMessage::ValidationVisitor& validation_visitor) override {
58
11
    const auto& typed_config = MessageUtil::downcastAndValidate<
59
11
        const envoy::extensions::matching::common_inputs::network::v3::DynamicMetadataInput&>(
60
11
        message, validation_visitor);
61
11
    auto config_ptr = std::make_shared<
62
11
        envoy::extensions::matching::common_inputs::network::v3::DynamicMetadataInput>(
63
11
        typed_config);
64
11
    return [config_ptr] {
65
11
      return std::make_unique<DynamicMetadataInput<MatchingDataType>>(*config_ptr);
66
11
    };
67
11
  };
68

            
69
14
  ProtobufTypes::MessagePtr createEmptyConfigProto() override {
70
14
    return std::make_unique<
71
14
        envoy::extensions::matching::common_inputs::network::v3::DynamicMetadataInput>();
72
14
  }
73
};
74

            
75
DECLARE_FACTORY(HttpDymanicMetadataInputFactory);
76

            
77
} // namespace MetadataInput
78
} // namespace Http
79
} // namespace Matching
80
} // namespace Extensions
81
} // namespace Envoy