1
#pragma once
2

            
3
#include <string>
4
#include <vector>
5

            
6
#include "envoy/config/route/v3/route_components.pb.h"
7
#include "envoy/config/typed_config.h"
8
#include "envoy/http/header_map.h"
9
#include "envoy/protobuf/message_validator.h"
10
#include "envoy/server/factory_context.h"
11
#include "envoy/stream_info/stream_info.h"
12
#include "envoy/type/v3/ratelimit_unit.pb.h"
13

            
14
#include "absl/time/time.h"
15
#include "absl/types/optional.h"
16

            
17
namespace Envoy {
18
namespace RateLimit {
19

            
20
/**
21
 * An optional dynamic override for the rate limit. See ratelimit.proto
22
 */
23
struct RateLimitOverride {
24
  uint32_t requests_per_unit_;
25
  envoy::type::v3::RateLimitUnit unit_;
26
};
27

            
28
/**
29
 * A single rate limit request descriptor entry. See ratelimit.proto.
30
 */
31
struct DescriptorEntry {
32
  std::string key_;
33
  std::string value_;
34

            
35
370
  friend bool operator==(const DescriptorEntry& lhs, const DescriptorEntry& rhs) {
36
370
    return lhs.key_ == rhs.key_ && lhs.value_ == rhs.value_;
37
370
  }
38
  template <typename H>
39
  friend H AbslHashValue(H h, // NOLINT(readability-identifier-naming)
40
280
                         const DescriptorEntry& entry) {
41
280
    return H::combine(std::move(h), entry.key_, entry.value_);
42
280
  }
43
};
44

            
45
using DescriptorEntries = std::vector<DescriptorEntry>;
46

            
47
using RateLimitProto = envoy::config::route::v3::RateLimit;
48
using XRateLimitOption = RateLimitProto::XRateLimitOption;
49

            
50
/**
51
 * A single rate limit request descriptor. This is generated by the rate limit filter
52
 * based on the configuration and the incoming request. And this will be used to match
53
 * the rate limit rule.
54
 */
55
struct Descriptor {
56
  DescriptorEntries entries_;
57
  absl::optional<RateLimitOverride> limit_ = absl::nullopt;
58
  absl::optional<uint64_t> hits_addend_ = absl::nullopt;
59
  XRateLimitOption x_ratelimit_option_{};
60

            
61
  std::string toString() const {
62
    return absl::StrJoin(entries_, ", ", [](std::string* out, const auto& e) {
63
      absl::StrAppend(out, e.key_, "=", e.value_);
64
    });
65
  }
66

            
67
  struct Hash {
68
    using is_transparent = void; // NOLINT(readability-identifier-naming)
69
71
    template <class DescriptorType> size_t operator()(const DescriptorType& d) const {
70
71
      return absl::Hash<DescriptorEntries>()(d.entries_);
71
71
    }
72
  };
73
  struct Equal {
74
    using is_transparent = void; // NOLINT(readability-identifier-naming)
75
    template <class DescriptorTypeA, class DescriptorTypeB>
76
93
    size_t operator()(const DescriptorTypeA& lhs, const DescriptorTypeB& rhs) const {
77
93
      return lhs.entries_ == rhs.entries_;
78
93
    }
79
  };
80

            
81
  /**
82
   * Descriptor map.
83
   */
84
  template <class V> using Map = absl::flat_hash_map<Descriptor, V, Hash, Equal>;
85
};
86

            
87
/**
88
 * A local descriptor is a set of descriptor entries that are used as the key of single
89
 * rate limit rule.
90
 */
91
struct LocalDescriptor {
92
  DescriptorEntries entries_;
93

            
94
  struct Hash {
95
    using is_transparent = void; // NOLINT(readability-identifier-naming)
96
146
    template <class DescriptorType> size_t operator()(const DescriptorType& d) const {
97
146
      return absl::Hash<DescriptorEntries>()(d.entries_);
98
146
    }
99
  };
100
  struct Equal {
101
    using is_transparent = void; // NOLINT(readability-identifier-naming)
102
    template <class DescriptorTypeA, class DescriptorTypeB>
103
121
    size_t operator()(const DescriptorTypeA& lhs, const DescriptorTypeB& rhs) const {
104
121
      return lhs.entries_ == rhs.entries_;
105
121
    }
106
  };
107

            
108
2
  std::string toString() const {
109
2
    return absl::StrJoin(entries_, ", ", [](std::string* out, const auto& e) {
110
2
      absl::StrAppend(out, e.key_, "=", e.value_);
111
2
    });
112
2
  }
113

            
114
  /**
115
   * Local descriptor map.
116
   */
117
  template <class V> using Map = absl::flat_hash_map<LocalDescriptor, V, Hash, Equal>;
118
};
119

            
120
/*
121
 * Base interface for generic rate limit descriptor producer.
122
 */
123
class DescriptorProducer {
124
public:
125
276
  virtual ~DescriptorProducer() = default;
126

            
127
  /**
128
   * Potentially fill a descriptor entry to the end of descriptor.
129
   * @param descriptor_entry supplies the descriptor entry to optionally fill.
130
   * @param local_service_cluster supplies the name of the local service cluster.
131
   * @param headers supplies the header for the request.
132
   * @param info stream info associated with the request
133
   * @return true if the producer populated the descriptor.
134
   */
135
  virtual bool populateDescriptor(DescriptorEntry& descriptor_entry,
136
                                  const std::string& local_service_cluster,
137
                                  const Http::RequestHeaderMap& headers,
138
                                  const StreamInfo::StreamInfo& info) const PURE;
139
};
140

            
141
using DescriptorProducerPtr = std::unique_ptr<DescriptorProducer>;
142

            
143
/**
144
 * Implemented by each custom rate limit descriptor extension and registered via
145
 * Registry::registerFactory() or the convenience class RegisterFactory.
146
 */
147
class DescriptorProducerFactory : public Config::TypedFactory {
148
public:
149
  ~DescriptorProducerFactory() override = default;
150

            
151
  /**
152
   * Creates a particular DescriptorProducer implementation.
153
   *
154
   * @param config supplies the configuration for the descriptor extension.
155
   * @param context supplies the factory context.
156
   * @return DescriptorProducerPtr the rate limit descriptor producer which will be used to
157
   * populate rate limit descriptors.
158
   */
159
  virtual absl::StatusOr<DescriptorProducerPtr>
160
  createDescriptorProducerFromProto(const Protobuf::Message& config,
161
                                    Server::Configuration::CommonFactoryContext& context) PURE;
162

            
163
10
  std::string category() const override { return "envoy.rate_limit_descriptors"; }
164
};
165

            
166
} // namespace RateLimit
167
} // namespace Envoy