1
#pragma once
2

            
3
#include <functional>
4
#include <iosfwd>
5
#include <memory>
6
#include <sstream>
7
#include <vector>
8

            
9
#include "absl/container/node_hash_map.h"
10
#include "absl/strings/escaping.h"
11
#include "fmt/format.h"
12
#include "fmt/ostream.h"
13

            
14
namespace Envoy {
15
namespace Http {
16

            
17
/**
18
 * Please refer to #2394 for more info about Envoy METADATA.
19
 * Envoy metadata docs can be found at source/docs/h2_metadata.md.
20
 */
21
constexpr uint8_t METADATA_FRAME_TYPE = 0x4d;
22
constexpr uint8_t END_METADATA_FLAG = 0x4;
23

            
24
// NGHTTP2_MAX_PAYLOADLEN in nghttp2.
25
// TODO(soya3129): Respect max_frame_size after nghttp2 #1250 is resolved.
26
constexpr uint64_t METADATA_MAX_PAYLOAD_SIZE = 16384;
27

            
28
using UnorderedStringMap = absl::node_hash_map<std::string, std::string>;
29

            
30
class MetadataMap : public UnorderedStringMap {
31
public:
32
  using UnorderedStringMap::UnorderedStringMap;
33

            
34
3
  friend std::ostream& operator<<(std::ostream& out, const MetadataMap& metadata_map) {
35
3
    out << "metadata map:";
36
12
    for (const auto& metadata : metadata_map) {
37
12
      out << "\nkey: " << absl::CEscape(metadata.first)
38
12
          << ", value: " << absl::CEscape(metadata.second) << std::endl;
39
12
    }
40
3
    return out;
41
3
  }
42
};
43

            
44
using MetadataMapPtr = std::unique_ptr<MetadataMap>;
45

            
46
using VectorMetadataMapPtr = std::vector<MetadataMapPtr>;
47

            
48
class MetadataMapVector : public VectorMetadataMapPtr {
49
public:
50
  using VectorMetadataMapPtr::VectorMetadataMapPtr;
51

            
52
  friend std::ostream& operator<<(std::ostream& out, const MetadataMapVector& metadata_map_vector) {
53
    out << "metadata_map_vector:\n";
54
    for (const auto& metadata_map : metadata_map_vector) {
55
      out << *metadata_map;
56
    }
57
    return out;
58
  }
59
};
60

            
61
using MetadataCallback = std::function<void(MetadataMapPtr&&)>;
62

            
63
} // namespace Http
64
} // namespace Envoy
65

            
66
// NOLINT(namespace-envoy)
67
namespace fmt {
68

            
69
// Specialize printing Envoy::Http::MetadataMap as we need to escape possible
70
// invalid utf8 string contained in MetadataMap.
71
template <> struct formatter<Envoy::Http::MetadataMap> {
72
  template <typename ParseContext>
73
2
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
74
2
    return ctx.begin();
75
2
  }
76

            
77
  template <typename FormatContext>
78
  auto format(const Envoy::Http::MetadataMap& map,
79
2
              FormatContext& ctx) const -> decltype(ctx.out()) {
80
2
    std::ostringstream out;
81
2
    out << map;
82
2
    auto str = out.str();
83
2
    return fmt::formatter<std::string>().format(str, ctx);
84
2
  }
85
};
86

            
87
template <> struct formatter<::Envoy::Http::MetadataMapVector> : fmt::ostream_formatter {};
88

            
89
} // namespace fmt