Line data Source code
1 : #include "source/extensions/formatter/cel/cel.h" 2 : 3 : #include "source/common/config/metadata.h" 4 : #include "source/common/formatter/substitution_formatter.h" 5 : #include "source/common/http/utility.h" 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 Formatter { 15 : 16 : namespace Expr = Filters::Common::Expr; 17 : 18 : CELFormatter::CELFormatter(const ::Envoy::LocalInfo::LocalInfo& local_info, 19 : Expr::BuilderInstanceSharedPtr expr_builder, 20 : const google::api::expr::v1alpha1::Expr& input_expr, 21 : absl::optional<size_t>& max_length) 22 : : local_info_(local_info), expr_builder_(expr_builder), parsed_expr_(input_expr), 23 0 : max_length_(max_length) { 24 0 : compiled_expr_ = Expr::createExpression(expr_builder_->builder(), parsed_expr_); 25 0 : } 26 : 27 : absl::optional<std::string> 28 : CELFormatter::formatWithContext(const Envoy::Formatter::HttpFormatterContext& context, 29 0 : const StreamInfo::StreamInfo& stream_info) const { 30 0 : Protobuf::Arena arena; 31 0 : auto eval_status = 32 0 : Expr::evaluate(*compiled_expr_, arena, &local_info_, stream_info, &context.requestHeaders(), 33 0 : &context.responseHeaders(), &context.responseTrailers()); 34 0 : if (!eval_status.has_value() || eval_status.value().IsError()) { 35 0 : return absl::nullopt; 36 0 : } 37 0 : const auto result = Expr::print(eval_status.value()); 38 0 : if (max_length_) { 39 0 : return result.substr(0, max_length_.value()); 40 0 : } 41 : 42 0 : return result; 43 0 : } 44 : 45 : ProtobufWkt::Value 46 : CELFormatter::formatValueWithContext(const Envoy::Formatter::HttpFormatterContext& context, 47 0 : const StreamInfo::StreamInfo& stream_info) const { 48 0 : auto result = formatWithContext(context, stream_info); 49 0 : if (!result.has_value()) { 50 0 : return ValueUtil::nullValue(); 51 0 : } 52 0 : return ValueUtil::stringValue(result.value()); 53 0 : } 54 : 55 : ::Envoy::Formatter::FormatterProviderPtr 56 : CELFormatterCommandParser::parse(const std::string& command, const std::string& subcommand, 57 0 : absl::optional<size_t>& max_length) const { 58 0 : #if defined(USE_CEL_PARSER) 59 0 : if (command == "CEL") { 60 0 : auto parse_status = google::api::expr::parser::Parse(subcommand); 61 0 : if (!parse_status.ok()) { 62 0 : throw EnvoyException("Not able to parse filter expression: " + 63 0 : parse_status.status().ToString()); 64 0 : } 65 : 66 0 : return std::make_unique<CELFormatter>(local_info_, expr_builder_, parse_status.value().expr(), 67 0 : max_length); 68 0 : } 69 : 70 0 : return nullptr; 71 : #else 72 : throw EnvoyException("CEL is not available for use in this environment."); 73 : #endif 74 0 : } 75 : 76 : } // namespace Formatter 77 : } // namespace Extensions 78 : } // namespace Envoy