Line data Source code
1 : #include "source/extensions/rate_limit_descriptors/expr/config.h" 2 : 3 : #include "envoy/extensions/rate_limit_descriptors/expr/v3/expr.pb.h" 4 : #include "envoy/extensions/rate_limit_descriptors/expr/v3/expr.pb.validate.h" 5 : 6 : #include "source/common/protobuf/utility.h" 7 : 8 : #if defined(USE_CEL_PARSER) 9 : #include "parser/parser.h" 10 : #endif 11 : 12 : namespace Envoy { 13 : namespace Extensions { 14 : namespace RateLimitDescriptors { 15 : namespace Expr { 16 : 17 : namespace { 18 : 19 : /** 20 : * Descriptor producer for a symbolic expression descriptor. 21 : */ 22 : class ExpressionDescriptor : public RateLimit::DescriptorProducer { 23 : public: 24 : ExpressionDescriptor( 25 : const envoy::extensions::rate_limit_descriptors::expr::v3::Descriptor& config, 26 : Extensions::Filters::Common::Expr::BuilderInstanceSharedPtr& builder, 27 : const google::api::expr::v1alpha1::Expr& input_expr) 28 : : builder_(builder), input_expr_(input_expr), descriptor_key_(config.descriptor_key()), 29 0 : skip_if_error_(config.skip_if_error()) { 30 0 : compiled_expr_ = 31 0 : Extensions::Filters::Common::Expr::createExpression(builder_->builder(), input_expr_); 32 0 : } 33 : 34 : // Ratelimit::DescriptorProducer 35 : bool populateDescriptor(RateLimit::DescriptorEntry& descriptor_entry, const std::string&, 36 : const Http::RequestHeaderMap& headers, 37 0 : const StreamInfo::StreamInfo& info) const override { 38 0 : ProtobufWkt::Arena arena; 39 0 : const auto result = Filters::Common::Expr::evaluate(*compiled_expr_.get(), arena, nullptr, info, 40 0 : &headers, nullptr, nullptr); 41 0 : if (!result.has_value() || result.value().IsError()) { 42 : // If result is an error and if skip_if_error is true skip this descriptor, 43 : // while calling rate limiting service. If skip_if_error is false, do not call rate limiting 44 : // service. 45 0 : return skip_if_error_; 46 0 : } 47 0 : descriptor_entry = {descriptor_key_, Filters::Common::Expr::print(result.value())}; 48 0 : return true; 49 0 : } 50 : 51 : private: 52 : Extensions::Filters::Common::Expr::BuilderInstanceSharedPtr builder_; 53 : const google::api::expr::v1alpha1::Expr input_expr_; 54 : const std::string descriptor_key_; 55 : const bool skip_if_error_; 56 : Extensions::Filters::Common::Expr::ExpressionPtr compiled_expr_; 57 : }; 58 : 59 : } // namespace 60 : 61 38 : std::string ExprDescriptorFactory::name() const { return "envoy.rate_limit_descriptors.expr"; } 62 : 63 1 : ProtobufTypes::MessagePtr ExprDescriptorFactory::createEmptyConfigProto() { 64 1 : return std::make_unique<envoy::extensions::rate_limit_descriptors::expr::v3::Descriptor>(); 65 1 : } 66 : 67 : RateLimit::DescriptorProducerPtr ExprDescriptorFactory::createDescriptorProducerFromProto( 68 0 : const Protobuf::Message& message, Server::Configuration::CommonFactoryContext& context) { 69 0 : const auto& config = MessageUtil::downcastAndValidate< 70 0 : const envoy::extensions::rate_limit_descriptors::expr::v3::Descriptor&>( 71 0 : message, context.messageValidationVisitor()); 72 0 : auto builder = Extensions::Filters::Common::Expr::getBuilder(context); 73 0 : switch (config.expr_specifier_case()) { 74 0 : #if defined(USE_CEL_PARSER) 75 0 : case envoy::extensions::rate_limit_descriptors::expr::v3::Descriptor::kText: { 76 0 : auto parse_status = google::api::expr::parser::Parse(config.text()); 77 0 : if (!parse_status.ok()) { 78 0 : throw EnvoyException("Unable to parse descriptor expression: " + 79 0 : parse_status.status().ToString()); 80 0 : } 81 0 : return std::make_unique<ExpressionDescriptor>(config, builder, parse_status.value().expr()); 82 0 : } 83 0 : #endif 84 0 : case envoy::extensions::rate_limit_descriptors::expr::v3::Descriptor::kParsed: 85 0 : return std::make_unique<ExpressionDescriptor>(config, builder, config.parsed()); 86 0 : default: 87 0 : return nullptr; 88 0 : } 89 0 : } 90 : 91 : REGISTER_FACTORY(ExprDescriptorFactory, RateLimit::DescriptorProducerFactory); 92 : 93 : } // namespace Expr 94 : } // namespace RateLimitDescriptors 95 : } // namespace Extensions 96 : } // namespace Envoy