1
#pragma once
2

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

            
6
#include "envoy/formatter/substitution_formatter.h"
7
#include "envoy/json/json_object.h"
8
#include "envoy/stream_info/stream_info.h"
9

            
10
#include "source/common/common/statusor.h"
11
#include "source/common/formatter/substitution_format_utility.h"
12

            
13
#include "absl/types/optional.h"
14

            
15
namespace Envoy {
16
namespace Formatter {
17

            
18
/**
19
 * CoalesceFormatter provides a higher-order formatter that evaluates multiple
20
 * formatter operators in sequence and returns the first non-null result.
21
 *
22
 * This formatter accepts a JSON configuration specifying an array of operators
23
 * to evaluate. Each operator can be either:
24
 * - A string representing a simple command (e.g., "REQUESTED_SERVER_NAME")
25
 * - An object with "command" and optional "param" and "max_length" fields
26
 *
27
 * Example JSON configuration:
28
 * {
29
 *   "operators": [
30
 *     "REQUESTED_SERVER_NAME",
31
 *     {"command": "REQ", "param": ":authority"},
32
 *     {"command": "REQ", "param": "host"}
33
 *   ]
34
 * }
35
 *
36
 * Note that the JSON parameter cannot contain literal ')' characters as they would
37
 * interfere with the command parser regex.
38
 */
39
class CoalesceFormatter : public FormatterProvider {
40
public:
41
  /**
42
   * Creates a CoalesceFormatter from a JSON configuration string.
43
   * @param json_config the JSON configuration string.
44
   * @param max_length optional maximum length for the output.
45
   * @return StatusOr containing the formatter or an error.
46
   */
47
  static absl::StatusOr<FormatterProviderPtr> create(absl::string_view json_config,
48
                                                     absl::optional<size_t> max_length);
49

            
50
  CoalesceFormatter(std::vector<FormatterProviderPtr>&& formatters,
51
                    absl::optional<size_t> max_length)
52
18
      : formatters_(std::move(formatters)), max_length_(max_length) {}
53

            
54
  // FormatterProvider interface.
55
  absl::optional<std::string> format(const Context& context,
56
                                     const StreamInfo::StreamInfo& stream_info) const override;
57
  Protobuf::Value formatValue(const Context& context,
58
                              const StreamInfo::StreamInfo& stream_info) const override;
59

            
60
private:
61
  /**
62
   * Parses a single operator entry from the JSON configuration.
63
   * @param entry the JSON object representing an operator entry.
64
   * @return StatusOr containing the formatter or an error.
65
   */
66
  static absl::StatusOr<FormatterProviderPtr> parseOperatorEntry(const Json::Object& entry);
67

            
68
  /**
69
   * Creates a formatter for the given command using built-in command parsers.
70
   * @param command the command name.
71
   * @param param the command parameter (may be empty).
72
   * @param max_length optional maximum length.
73
   * @return StatusOr containing the formatter or an error.
74
   */
75
  static absl::StatusOr<FormatterProviderPtr>
76
  createFormatterForCommand(absl::string_view command, absl::string_view param,
77
                            absl::optional<size_t> max_length);
78

            
79
  std::vector<FormatterProviderPtr> formatters_;
80
  absl::optional<size_t> max_length_;
81
};
82

            
83
} // namespace Formatter
84
} // namespace Envoy