1
#include "source/common/formatter/http_specific_formatter.h"
2

            
3
#include "source/common/common/assert.h"
4
#include "source/common/common/empty_string.h"
5
#include "source/common/common/fmt.h"
6
#include "source/common/common/thread.h"
7
#include "source/common/common/utility.h"
8
#include "source/common/config/metadata.h"
9
#include "source/common/formatter/coalesce_formatter.h"
10
#include "source/common/grpc/common.h"
11
#include "source/common/grpc/status.h"
12
#include "source/common/http/header_map_impl.h"
13
#include "source/common/http/utility.h"
14
#include "source/common/protobuf/message_validator_impl.h"
15
#include "source/common/protobuf/utility.h"
16
#include "source/common/runtime/runtime_features.h"
17
#include "source/common/stream_info/utility.h"
18

            
19
namespace Envoy {
20
namespace Formatter {
21

            
22
absl::optional<std::string> LocalReplyBodyFormatter::format(const Context& context,
23
40
                                                            const StreamInfo::StreamInfo&) const {
24
40
  return std::string(context.localReplyBody());
25
40
}
26

            
27
Protobuf::Value LocalReplyBodyFormatter::formatValue(const Context& context,
28
44
                                                     const StreamInfo::StreamInfo&) const {
29
44
  return ValueUtil::stringValue(std::string(context.localReplyBody()));
30
44
}
31

            
32
absl::optional<std::string> AccessLogTypeFormatter::format(const Context& context,
33
467
                                                           const StreamInfo::StreamInfo&) const {
34
467
  return AccessLogType_Name(context.accessLogType());
35
467
}
36

            
37
Protobuf::Value AccessLogTypeFormatter::formatValue(const Context& context,
38
11
                                                    const StreamInfo::StreamInfo&) const {
39
11
  return ValueUtil::stringValue(AccessLogType_Name(context.accessLogType()));
40
11
}
41

            
42
HeaderFormatter::HeaderFormatter(absl::string_view main_header,
43
                                 absl::string_view alternative_header,
44
                                 absl::optional<size_t> max_length)
45
133517
    : main_header_(main_header), alternative_header_(alternative_header), max_length_(max_length) {}
46

            
47
506449
const Http::HeaderEntry* HeaderFormatter::findHeader(OptRef<const Http::HeaderMap> headers) const {
48
506449
  if (!headers.has_value()) {
49
61373
    return nullptr;
50
61373
  }
51

            
52
445076
  const auto header = headers->get(main_header_);
53

            
54
445076
  if (header.empty() && !alternative_header_.get().empty()) {
55
69624
    const auto alternate_header = headers->get(alternative_header_);
56
    // TODO(https://github.com/envoyproxy/envoy/issues/13454): Potentially log all header values.
57
69624
    return alternate_header.empty() ? nullptr : alternate_header[0];
58
69624
  }
59

            
60
375452
  return header.empty() ? nullptr : header[0];
61
445076
}
62

            
63
506288
absl::optional<std::string> HeaderFormatter::format(OptRef<const Http::HeaderMap> headers) const {
64
506288
  const Http::HeaderEntry* header = findHeader(headers);
65
506288
  if (!header) {
66
212687
    return absl::nullopt;
67
212687
  }
68

            
69
293601
  absl::string_view val = header->value().getStringView();
70
293601
  val = SubstitutionFormatUtils::truncateStringView(val, max_length_);
71
293601
  return std::string(val);
72
506288
}
73

            
74
161
Protobuf::Value HeaderFormatter::formatValue(OptRef<const Http::HeaderMap> headers) const {
75
161
  const Http::HeaderEntry* header = findHeader(headers);
76
161
  if (!header) {
77
117
    return SubstitutionFormatUtils::unspecifiedValue();
78
117
  }
79

            
80
44
  absl::string_view val = header->value().getStringView();
81
44
  val = SubstitutionFormatUtils::truncateStringView(val, max_length_);
82
44
  return ValueUtil::stringValue(std::string(val));
83
161
}
84

            
85
ResponseHeaderFormatter::ResponseHeaderFormatter(absl::string_view main_header,
86
                                                 absl::string_view alternative_header,
87
                                                 absl::optional<size_t> max_length)
88
19152
    : HeaderFormatter(main_header, alternative_header, max_length) {}
89

            
90
absl::optional<std::string> ResponseHeaderFormatter::format(const Context& context,
91
72485
                                                            const StreamInfo::StreamInfo&) const {
92
72485
  return HeaderFormatter::format(context.responseHeaders());
93
72485
}
94

            
95
Protobuf::Value ResponseHeaderFormatter::formatValue(const Context& context,
96
12
                                                     const StreamInfo::StreamInfo&) const {
97
12
  return HeaderFormatter::formatValue(context.responseHeaders());
98
12
}
99

            
100
RequestHeaderFormatter::RequestHeaderFormatter(absl::string_view main_header,
101
                                               absl::string_view alternative_header,
102
                                               absl::optional<size_t> max_length)
103
114325
    : HeaderFormatter(main_header, alternative_header, max_length) {}
104

            
105
absl::optional<std::string> RequestHeaderFormatter::format(const Context& context,
106
433782
                                                           const StreamInfo::StreamInfo&) const {
107
433782
  return HeaderFormatter::format(context.requestHeaders());
108
433782
}
109

            
110
Protobuf::Value RequestHeaderFormatter::formatValue(const Context& context,
111
144
                                                    const StreamInfo::StreamInfo&) const {
112
144
  return HeaderFormatter::formatValue(context.requestHeaders());
113
144
}
114

            
115
ResponseTrailerFormatter::ResponseTrailerFormatter(absl::string_view main_header,
116
                                                   absl::string_view alternative_header,
117
                                                   absl::optional<size_t> max_length)
118
19
    : HeaderFormatter(main_header, alternative_header, max_length) {}
119

            
120
absl::optional<std::string> ResponseTrailerFormatter::format(const Context& context,
121
21
                                                             const StreamInfo::StreamInfo&) const {
122
21
  return HeaderFormatter::format(context.responseTrailers());
123
21
}
124

            
125
Protobuf::Value ResponseTrailerFormatter::formatValue(const Context& context,
126
5
                                                      const StreamInfo::StreamInfo&) const {
127
5
  return HeaderFormatter::formatValue(context.responseTrailers());
128
5
}
129

            
130
HeadersByteSizeFormatter::HeadersByteSizeFormatter(const HeaderType header_type)
131
9
    : header_type_(header_type) {}
132

            
133
uint64_t HeadersByteSizeFormatter::extractHeadersByteSize(
134
    OptRef<const Http::RequestHeaderMap> request_headers,
135
    OptRef<const Http::ResponseHeaderMap> response_headers,
136
12
    OptRef<const Http::ResponseTrailerMap> response_trailers) const {
137
12
  switch (header_type_) {
138
4
  case HeaderType::RequestHeaders:
139
4
    return request_headers.has_value() ? request_headers->byteSize() : 0;
140
4
  case HeaderType::ResponseHeaders:
141
4
    return response_headers.has_value() ? response_headers->byteSize() : 0;
142
4
  case HeaderType::ResponseTrailers:
143
4
    return response_trailers.has_value() ? response_trailers->byteSize() : 0;
144
12
  }
145
  PANIC_DUE_TO_CORRUPT_ENUM;
146
}
147

            
148
absl::optional<std::string> HeadersByteSizeFormatter::format(const Context& context,
149
9
                                                             const StreamInfo::StreamInfo&) const {
150
9
  return absl::StrCat(extractHeadersByteSize(context.requestHeaders(), context.responseHeaders(),
151
9
                                             context.responseTrailers()));
152
9
}
153

            
154
Protobuf::Value HeadersByteSizeFormatter::formatValue(const Context& context,
155
3
                                                      const StreamInfo::StreamInfo&) const {
156
3
  return ValueUtil::numberValue(extractHeadersByteSize(
157
3
      context.requestHeaders(), context.responseHeaders(), context.responseTrailers()));
158
3
}
159

            
160
Protobuf::Value TraceIDFormatter::formatValue(const Context& context,
161
2
                                              const StreamInfo::StreamInfo&) const {
162
2
  const auto active_span = context.activeSpan();
163
2
  if (!active_span.has_value()) {
164
1
    return SubstitutionFormatUtils::unspecifiedValue();
165
1
  }
166
1
  auto trace_id = active_span->getTraceId();
167
1
  if (trace_id.empty()) {
168
    return SubstitutionFormatUtils::unspecifiedValue();
169
  }
170
1
  return ValueUtil::stringValue(trace_id);
171
1
}
172

            
173
absl::optional<std::string> TraceIDFormatter::format(const Context& context,
174
10
                                                     const StreamInfo::StreamInfo&) const {
175
10
  const auto active_span = context.activeSpan();
176
10
  if (!active_span.has_value()) {
177
1
    return absl::nullopt;
178
1
  }
179

            
180
9
  auto trace_id = active_span->getTraceId();
181
9
  if (trace_id.empty()) {
182
3
    return absl::nullopt;
183
3
  }
184
6
  return trace_id;
185
9
}
186

            
187
16
GrpcStatusFormatter::Format GrpcStatusFormatter::parseFormat(absl::string_view format) {
188
16
  if (format.empty() || format == "CAMEL_STRING") {
189
9
    return GrpcStatusFormatter::CamelString;
190
9
  }
191

            
192
7
  if (format == "SNAKE_STRING") {
193
3
    return GrpcStatusFormatter::SnakeString;
194
3
  }
195
4
  if (format == "NUMBER") {
196
3
    return GrpcStatusFormatter::Number;
197
3
  }
198

            
199
1
  throw EnvoyException("GrpcStatusFormatter only supports CAMEL_STRING, SNAKE_STRING or NUMBER.");
200
4
}
201

            
202
GrpcStatusFormatter::GrpcStatusFormatter(const std::string& main_header,
203
                                         const std::string& alternative_header,
204
                                         absl::optional<size_t> max_length, Format format)
205
21
    : HeaderFormatter(main_header, alternative_header, max_length), format_(format) {}
206

            
207
absl::optional<std::string> GrpcStatusFormatter::format(const Context& context,
208
90
                                                        const StreamInfo::StreamInfo& info) const {
209
90
  if (!Grpc::Common::isGrpcRequestHeaders(
210
90
          context.requestHeaders().value_or(*Http::StaticEmptyHeaders::get().request_headers))) {
211
6
    return absl::nullopt;
212
6
  }
213
84
  const auto grpc_status = Grpc::Common::getGrpcStatus(
214
84
      context.responseTrailers().value_or(*Http::StaticEmptyHeaders::get().response_trailers),
215
84
      context.responseHeaders().value_or(*Http::StaticEmptyHeaders::get().response_headers), info,
216
84
      true);
217
84
  if (!grpc_status.has_value()) {
218
3
    return absl::nullopt;
219
3
  }
220
81
  switch (format_) {
221
30
  case CamelString: {
222
30
    const auto grpc_status_message = Grpc::Utility::grpcStatusToString(grpc_status.value());
223
30
    if (grpc_status_message == EMPTY_STRING || grpc_status_message == "InvalidCode") {
224
7
      return std::to_string(grpc_status.value());
225
7
    }
226
23
    return grpc_status_message;
227
30
  }
228
24
  case SnakeString: {
229
24
    const auto grpc_status_message =
230
24
        absl::StatusCodeToString(static_cast<absl::StatusCode>(grpc_status.value()));
231
24
    if (grpc_status_message == EMPTY_STRING) {
232
5
      return std::to_string(grpc_status.value());
233
5
    }
234
19
    return grpc_status_message;
235
24
  }
236
27
  case Number: {
237
27
    return std::to_string(grpc_status.value());
238
24
  }
239
81
  }
240
  PANIC_DUE_TO_CORRUPT_ENUM;
241
}
242

            
243
Protobuf::Value GrpcStatusFormatter::formatValue(const Context& context,
244
72
                                                 const StreamInfo::StreamInfo& info) const {
245
72
  if (!Grpc::Common::isGrpcRequestHeaders(
246
72
          context.requestHeaders().value_or(*Http::StaticEmptyHeaders::get().request_headers))) {
247
6
    return SubstitutionFormatUtils::unspecifiedValue();
248
6
  }
249
66
  const auto grpc_status = Grpc::Common::getGrpcStatus(
250
66
      context.responseTrailers().value_or(*Http::StaticEmptyHeaders::get().response_trailers),
251
66
      context.responseHeaders().value_or(*Http::StaticEmptyHeaders::get().response_headers), info,
252
66
      true);
253
66
  if (!grpc_status.has_value()) {
254
3
    return SubstitutionFormatUtils::unspecifiedValue();
255
3
  }
256

            
257
63
  switch (format_) {
258
21
  case CamelString: {
259
21
    const auto grpc_status_message = Grpc::Utility::grpcStatusToString(grpc_status.value());
260
21
    if (grpc_status_message == EMPTY_STRING || grpc_status_message == "InvalidCode") {
261
4
      return ValueUtil::stringValue(std::to_string(grpc_status.value()));
262
4
    }
263
17
    return ValueUtil::stringValue(grpc_status_message);
264
21
  }
265
21
  case SnakeString: {
266
21
    const auto grpc_status_message =
267
21
        absl::StatusCodeToString(static_cast<absl::StatusCode>(grpc_status.value()));
268
21
    if (grpc_status_message == EMPTY_STRING) {
269
4
      return ValueUtil::stringValue(std::to_string(grpc_status.value()));
270
4
    }
271
17
    return ValueUtil::stringValue(grpc_status_message);
272
21
  }
273
21
  case Number: {
274
21
    return ValueUtil::numberValue(grpc_status.value());
275
21
  }
276
63
  }
277
  PANIC_DUE_TO_CORRUPT_ENUM;
278
}
279

            
280
QueryParameterFormatter::QueryParameterFormatter(absl::string_view parameter_key,
281
                                                 absl::optional<size_t> max_length)
282
3
    : parameter_key_(parameter_key), max_length_(max_length) {}
283

            
284
// FormatterProvider
285
absl::optional<std::string> QueryParameterFormatter::format(const Context& context,
286
6
                                                            const StreamInfo::StreamInfo&) const {
287
6
  const auto request_headers = context.requestHeaders();
288
6
  if (!request_headers.has_value()) {
289
    return absl::nullopt;
290
  }
291

            
292
6
  const auto query_params =
293
6
      Http::Utility::QueryParamsMulti::parseAndDecodeQueryString(request_headers->getPathValue());
294
6
  absl::optional<std::string> value = query_params.getFirstValue(parameter_key_);
295
6
  if (value.has_value() && max_length_.has_value()) {
296
2
    SubstitutionFormatUtils::truncate(value.value(), max_length_.value());
297
2
  }
298
6
  return value;
299
6
}
300

            
301
Protobuf::Value
302
QueryParameterFormatter::formatValue(const Context& context,
303
3
                                     const StreamInfo::StreamInfo& stream_info) const {
304
3
  return ValueUtil::optionalStringValue(format(context, stream_info));
305
3
}
306

            
307
QueryParametersFormatter::DecodeOption
308
7
QueryParametersFormatter::parseDecodeOption(absl::string_view decoding) {
309

            
310
7
  if (decoding.empty() || decoding == "ORIG") {
311
4
    return DecodeOption::Original;
312
4
  } else if (decoding == "DECODED") {
313
2
    return DecodeOption::Decoded;
314
2
  } else {
315
1
    throw EnvoyException(fmt::format(
316
1
        "Invalid QUERY_PARAMS option: '{}', only 'ORIG'/'DECODED' are allowed", decoding));
317
1
  }
318
7
}
319

            
320
// FormatterProvider
321
absl::optional<std::string> QueryParametersFormatter::format(const Context& context,
322
12
                                                             const StreamInfo::StreamInfo&) const {
323
12
  const auto request_headers = context.requestHeaders();
324
12
  if (!request_headers.has_value()) {
325
    return absl::nullopt;
326
  }
327

            
328
  // Gather query parameters substring from path
329
12
  absl::string_view path_view = request_headers->getPathValue();
330
12
  auto query_offset = path_view.find('?');
331

            
332
12
  if (query_offset == absl::string_view::npos) {
333
    return absl::nullopt;
334
  }
335

            
336
12
  std::string query_params = std::string(path_view.substr(query_offset + 1));
337

            
338
  // Apply percent decoding on the query params if requested
339
12
  if (option_ == DecodeOption::Decoded) {
340
4
    query_params = Http::Utility::PercentEncoding::urlDecodeQueryParameter(query_params);
341
4
  }
342

            
343
12
  SubstitutionFormatUtils::truncate(query_params, max_length_);
344
12
  return query_params;
345
12
}
346

            
347
Protobuf::Value
348
QueryParametersFormatter::formatValue(const Context& context,
349
6
                                      const StreamInfo::StreamInfo& stream_info) const {
350
6
  return ValueUtil::optionalStringValue(format(context, stream_info));
351
6
}
352

            
353
absl::optional<std::string> PathFormatter::format(const Context& context,
354
50
                                                  const StreamInfo::StreamInfo&) const {
355

            
356
50
  absl::string_view path_view;
357
50
  const auto headers = context.requestHeaders();
358
50
  if (!headers.has_value()) {
359
    return absl::nullopt;
360
  }
361
50
  switch (option_) {
362
24
  case OriginalPathOrPath:
363
24
    path_view = headers->getEnvoyOriginalPathValue();
364
24
    if (path_view.empty()) {
365
12
      path_view = headers->getPathValue();
366
12
    }
367
24
    break;
368
14
  case PathOnly:
369
14
    path_view = headers->getPathValue();
370
14
    break;
371
12
  case OriginalPathOnly:
372
12
    path_view = headers->getEnvoyOriginalPathValue();
373
12
    break;
374
50
  }
375

            
376
50
  if (path_view.empty()) {
377
6
    return absl::nullopt;
378
6
  }
379

            
380
  // Strip query parameters if needed.
381
44
  if (!with_query_) {
382
16
    auto query_offset = path_view.find('?');
383
16
    if (query_offset != absl::string_view::npos) {
384
8
      path_view = path_view.substr(0, query_offset);
385
8
    }
386
16
  }
387

            
388
44
  path_view = SubstitutionFormatUtils::truncateStringView(path_view, max_length_);
389
44
  return std::string(path_view);
390
50
}
391

            
392
Protobuf::Value PathFormatter::formatValue(const Context& context,
393
                                           const StreamInfo::StreamInfo& stream_info) const {
394
  return ValueUtil::optionalStringValue(format(context, stream_info));
395
}
396

            
397
absl::StatusOr<FormatterProviderPtr> PathFormatter::create(absl::string_view with_query,
398
                                                           absl::string_view option,
399
15
                                                           absl::optional<size_t> max_length) {
400
15
  bool with_query_bool = true;
401
15
  PathFormatterOption option_enum = OriginalPathOrPath;
402

            
403
15
  if (with_query == "WQ") {
404
4
    with_query_bool = true;
405
11
  } else if (with_query == "NQ") {
406
6
    with_query_bool = false;
407
6
  } else if (with_query.empty()) {
408
4
    with_query_bool = true;
409
4
  } else {
410
1
    return absl::InvalidArgumentError(
411
1
        fmt::format("Invalid PATH option: '{}', only 'WQ'/'NQ' are allowed", with_query));
412
1
  }
413

            
414
14
  if (option == "ORIG") {
415
3
    option_enum = OriginalPathOnly;
416
11
  } else if (option == "PATH") {
417
4
    option_enum = PathOnly;
418
8
  } else if (option == "ORIG_OR_PATH") {
419
3
    option_enum = OriginalPathOrPath;
420
4
  } else if (option.empty()) {
421
3
    option_enum = OriginalPathOrPath;
422
3
  } else {
423
1
    return absl::InvalidArgumentError(fmt::format(
424
1
        "Invalid PATH option: '{}', only 'ORIG'/'PATH'/'ORIG_OR_PATH' are allowed", option));
425
1
  }
426

            
427
13
  return std::make_unique<PathFormatter>(with_query_bool, option_enum, max_length);
428
14
}
429

            
430
const BuiltInHttpCommandParser::FormatterProviderLookupTbl&
431
186491
BuiltInHttpCommandParser::getKnownFormatters() {
432
186491
  CONSTRUCT_ON_FIRST_USE(
433
186491
      FormatterProviderLookupTbl,
434
186491
      {{"REQ", // Same as REQUEST_HEADER and used for backward compatibility.
435
186491
        {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
436
186491
         [](absl::string_view format, absl::optional<size_t> max_length) {
437
186491
           auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
438
186491
           THROW_IF_NOT_OK_REF(result.status());
439
186491
           return std::make_unique<RequestHeaderFormatter>(result.value().first,
440
186491
                                                           result.value().second, max_length);
441
186491
         }}},
442
186491
       {"REQUEST_HEADER",
443
186491
        {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
444
186491
         [](absl::string_view format, absl::optional<size_t> max_length) {
445
186491
           auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
446
186491
           THROW_IF_NOT_OK_REF(result.status());
447
186491
           return std::make_unique<RequestHeaderFormatter>(result.value().first,
448
186491
                                                           result.value().second, max_length);
449
186491
         }}},
450
186491
       {"RESP", // Same as RESPONSE_HEADER and used for backward compatibility.
451
186491
        {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
452
186491
         [](absl::string_view format, absl::optional<size_t> max_length) {
453
186491
           auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
454
186491
           THROW_IF_NOT_OK_REF(result.status());
455
186491
           return std::make_unique<ResponseHeaderFormatter>(result.value().first,
456
186491
                                                            result.value().second, max_length);
457
186491
         }}},
458
186491
       {"RESPONSE_HEADER",
459
186491
        {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
460
186491
         [](absl::string_view format, absl::optional<size_t> max_length) {
461
186491
           auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
462
186491
           THROW_IF_NOT_OK_REF(result.status());
463
186491
           return std::make_unique<ResponseHeaderFormatter>(result.value().first,
464
186491
                                                            result.value().second, max_length);
465
186491
         }}},
466
186491
       {"TRAILER", // Same as RESPONSE_TRAILER and used for backward compatibility.
467
186491
        {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
468
186491
         [](absl::string_view format, absl::optional<size_t> max_length) {
469
186491
           auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
470
186491
           THROW_IF_NOT_OK_REF(result.status());
471
186491
           return std::make_unique<ResponseTrailerFormatter>(result.value().first,
472
186491
                                                             result.value().second, max_length);
473
186491
         }}},
474
186491
       {"RESPONSE_TRAILER",
475
186491
        {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
476
186491
         [](absl::string_view format, absl::optional<size_t> max_length) {
477
186491
           auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
478
186491
           THROW_IF_NOT_OK_REF(result.status());
479
186491
           return std::make_unique<ResponseTrailerFormatter>(result.value().first,
480
186491
                                                             result.value().second, max_length);
481
186491
         }}},
482
186491
       {"LOCAL_REPLY_BODY",
483
186491
        {CommandSyntaxChecker::COMMAND_ONLY,
484
186491
         [](absl::string_view, absl::optional<size_t>) {
485
186491
           return std::make_unique<LocalReplyBodyFormatter>();
486
186491
         }}},
487
186491
       {"ACCESS_LOG_TYPE",
488
186491
        {CommandSyntaxChecker::COMMAND_ONLY,
489
186491
         [](absl::string_view, absl::optional<size_t>) {
490
186491
           return std::make_unique<AccessLogTypeFormatter>();
491
186491
         }}},
492
186491
       {"GRPC_STATUS",
493
186491
        {CommandSyntaxChecker::PARAMS_OPTIONAL,
494
186491
         [](absl::string_view format, absl::optional<size_t>) {
495
186491
           return std::make_unique<GrpcStatusFormatter>("grpc-status", "", absl::optional<size_t>(),
496
186491
                                                        GrpcStatusFormatter::parseFormat(format));
497
186491
         }}},
498
186491
       {"GRPC_STATUS_NUMBER",
499
186491
        {CommandSyntaxChecker::COMMAND_ONLY,
500
186491
         [](absl::string_view, absl::optional<size_t>) {
501
186491
           return std::make_unique<GrpcStatusFormatter>("grpc-status", "", absl::optional<size_t>(),
502
186491
                                                        GrpcStatusFormatter::Number);
503
186491
         }}},
504
186491
       {"REQUEST_HEADERS_BYTES",
505
186491
        {CommandSyntaxChecker::COMMAND_ONLY,
506
186491
         [](absl::string_view, absl::optional<size_t>) {
507
186491
           return std::make_unique<HeadersByteSizeFormatter>(
508
186491
               HeadersByteSizeFormatter::HeaderType::RequestHeaders);
509
186491
         }}},
510
186491
       {"RESPONSE_HEADERS_BYTES",
511
186491
        {CommandSyntaxChecker::COMMAND_ONLY,
512
186491
         [](absl::string_view, absl::optional<size_t>) {
513
186491
           return std::make_unique<HeadersByteSizeFormatter>(
514
186491
               HeadersByteSizeFormatter::HeaderType::ResponseHeaders);
515
186491
         }}},
516
186491
       {"RESPONSE_TRAILERS_BYTES",
517
186491
        {CommandSyntaxChecker::COMMAND_ONLY,
518
186491
         [](absl::string_view, absl::optional<size_t>) {
519
186491
           return std::make_unique<HeadersByteSizeFormatter>(
520
186491
               HeadersByteSizeFormatter::HeaderType::ResponseTrailers);
521
186491
         }}},
522
186491
       {"STREAM_INFO_REQ",
523
186491
        {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
524
186491
         [](absl::string_view format, absl::optional<size_t> max_length) {
525
186491
           auto result = SubstitutionFormatUtils::parseSubcommandHeaders(format);
526
186491
           THROW_IF_NOT_OK_REF(result.status());
527
186491
           return std::make_unique<RequestHeaderFormatter>(result.value().first,
528
186491
                                                           result.value().second, max_length);
529
186491
         }}},
530
186491
       {"TRACE_ID",
531
186491
        {CommandSyntaxChecker::COMMAND_ONLY,
532
186491
         [](absl::string_view, absl::optional<size_t>) {
533
186491
           return std::make_unique<TraceIDFormatter>();
534
186491
         }}},
535
186491
       {"QUERY_PARAM",
536
186491
        {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
537
186491
         [](absl::string_view format, absl::optional<size_t> max_length) {
538
186491
           return std::make_unique<QueryParameterFormatter>(std::string(format), max_length);
539
186491
         }}},
540
186491
       {"QUERY_PARAMS",
541
186491
        {CommandSyntaxChecker::PARAMS_OPTIONAL | CommandSyntaxChecker::LENGTH_ALLOWED,
542
186491
         [](absl::string_view decoding, absl::optional<size_t> max_length) {
543
186491
           return std::make_unique<QueryParametersFormatter>(
544
186491
               QueryParametersFormatter::parseDecodeOption(decoding), max_length);
545
186491
         }}},
546
186491
       {"PATH",
547
186491
        {CommandSyntaxChecker::PARAMS_OPTIONAL | CommandSyntaxChecker::LENGTH_ALLOWED,
548
186491
         [](absl::string_view format, absl::optional<size_t> max_length) {
549
186491
           absl::string_view query;
550
186491
           absl::string_view option;
551
186491
           SubstitutionFormatUtils::parseSubcommand(format, ':', query, option);
552
186491
           return THROW_OR_RETURN_VALUE(PathFormatter::create(query, option, max_length),
553
186491
                                        FormatterProviderPtr);
554
186491
         }}},
555
186491
       {"COALESCE",
556
186491
        {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED,
557
186491
         [](absl::string_view format, absl::optional<size_t> max_length) {
558
186491
           return THROW_OR_RETURN_VALUE(CoalesceFormatter::create(format, max_length),
559
186491
                                        FormatterProviderPtr);
560
186491
         }}}});
561
186491
}
562

            
563
FormatterProviderPtr BuiltInHttpCommandParser::parse(absl::string_view command,
564
                                                     absl::string_view subcommand,
565
186491
                                                     absl::optional<size_t> max_length) const {
566
186491
  const FormatterProviderLookupTbl& providers = getKnownFormatters();
567

            
568
186491
  auto it = providers.find(command);
569

            
570
186491
  if (it == providers.end()) {
571
52705
    return nullptr;
572
52705
  }
573

            
574
  // Check flags for the command.
575
133786
  THROW_IF_NOT_OK(
576
133786
      CommandSyntaxChecker::verifySyntax((*it).second.first, command, subcommand, max_length));
577

            
578
  // Create a pointer to the formatter by calling a function
579
  // associated with formatter's name.
580
133784
  return (*it).second.second(subcommand, max_length);
581
133786
}
582

            
583
578
std::string DefaultBuiltInHttpCommandParserFactory::name() const {
584
578
  return "envoy.built_in_formatters.http.default";
585
578
}
586

            
587
536
CommandParserPtr DefaultBuiltInHttpCommandParserFactory::createCommandParser() const {
588
536
  return std::make_unique<BuiltInHttpCommandParser>();
589
536
}
590

            
591
REGISTER_FACTORY(DefaultBuiltInHttpCommandParserFactory, BuiltInCommandParserFactory);
592

            
593
} // namespace Formatter
594
} // namespace Envoy