Line data Source code
1 : #pragma once 2 : 3 : #include <string> 4 : #include <vector> 5 : 6 : #include "envoy/http/protocol.h" 7 : #include "envoy/stream_info/stream_info.h" 8 : 9 : #include "absl/strings/str_format.h" 10 : #include "absl/strings/str_replace.h" 11 : #include "absl/strings/str_split.h" 12 : #include "absl/types/optional.h" 13 : #include "fmt/format.h" 14 : 15 : namespace Envoy { 16 : namespace Formatter { 17 : 18 : class CommandSyntaxChecker { 19 : public: 20 : using CommandSyntaxFlags = std::bitset<4>; 21 : static constexpr CommandSyntaxFlags COMMAND_ONLY = 0; 22 : static constexpr CommandSyntaxFlags PARAMS_REQUIRED = 1 << 0; 23 : static constexpr CommandSyntaxFlags PARAMS_OPTIONAL = 1 << 1; 24 : static constexpr CommandSyntaxFlags LENGTH_ALLOWED = 1 << 2; 25 : 26 : static void verifySyntax(CommandSyntaxChecker::CommandSyntaxFlags flags, 27 : const std::string& command, const std::string& subcommand, 28 : const absl::optional<size_t>& length); 29 : }; 30 : 31 : /** 32 : * Context independent utility class for the formatter. 33 : */ 34 : class SubstitutionFormatUtils { 35 : public: 36 : // Optional references are not supported, but this method has large performance 37 : // impact, so using reference_wrapper. 38 : static const absl::optional<std::reference_wrapper<const std::string>> 39 : protocolToString(const absl::optional<Http::Protocol>& protocol); 40 : static const std::string& 41 : protocolToStringOrDefault(const absl::optional<Http::Protocol>& protocol); 42 : static const absl::optional<std::string> getHostname(); 43 : static const std::string getHostnameOrDefault(); 44 : 45 : /** 46 : * Unspecified value for protobuf. 47 : */ 48 : static const ProtobufWkt::Value& unspecifiedValue(); 49 : 50 : /** 51 : * Truncate a string to a maximum length. Do nothing if max_length is not set or 52 : * max_length is greater than the length of the string. 53 : */ 54 : static void truncate(std::string& str, absl::optional<size_t> max_length); 55 : 56 : /** 57 : * Parse a header subcommand of the form: X?Y . 58 : * Will populate a main_header and an optional alternative header if specified. 59 : * See doc: 60 : * https://envoyproxy.io/docs/envoy/latest/configuration/observability/access_log/access_log#format-rules 61 : */ 62 : static void parseSubcommandHeaders(const std::string& subcommand, std::string& main_header, 63 : std::string& alternative_header); 64 : 65 : /* Variadic function template to parse the 66 : subcommand and assign found tokens to sequence of params. 67 : subcommand must be a sequence 68 : of tokens separated by the same separator, like: header1:header2 or header1?header2?header3. 69 : params must be a sequence of std::string& with optional container storing std::string. Here are 70 : examples of params: 71 : - std::string& token1 72 : - std::string& token1, std::string& token2 73 : - std::string& token1, std::string& token2, std::vector<std::string>& remaining 74 : 75 : If command contains more tokens than number of passed params, unassigned tokens will be 76 : ignored. If command contains less tokens than number of passed params, some params will be left 77 : untouched. 78 : */ 79 : template <typename... Tokens> 80 : static void parseSubcommand(const std::string& subcommand, const char separator, 81 1705 : Tokens&&... params) { 82 1705 : std::vector<absl::string_view> tokens; 83 1705 : tokens = absl::StrSplit(subcommand, separator); 84 1705 : std::vector<absl::string_view>::iterator it = tokens.begin(); 85 1705 : ( 86 5063 : [&](auto& param) { 87 5063 : if (it != tokens.end()) { 88 2030 : if constexpr (std::is_same_v<typename std::remove_reference<decltype(param)>::type, 89 2030 : std::string>) { 90 : // Compile time handler for std::string. 91 2004 : param = std::string(*it); 92 2004 : it++; 93 2004 : } else { 94 : // Compile time handler for container type. It will catch all remaining tokens and 95 : // move iterator to the end. 96 38 : do { 97 38 : param.push_back(std::string(*it)); 98 38 : it++; 99 38 : } while (it != tokens.end()); 100 26 : } 101 2030 : } 102 5063 : }(params), 103 1705 : ...); 104 1705 : } 105 : }; 106 : 107 : } // namespace Formatter 108 : } // namespace Envoy