userver: userver/baggage/baggage.hpp Source File
Loading...
Searching...
No Matches
baggage.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/baggage/baggage.hpp
4/// @brief @copybrief baggage::Baggage
5
6#include <algorithm> // TODO: remove
7#include <optional>
8#include <stdexcept>
9#include <string>
10#include <string_view>
11#include <unordered_set>
12#include <vector>
13
14#include <userver/engine/task/inherited_variable.hpp>
15
16USERVER_NAMESPACE_BEGIN
17
18namespace baggage {
19
20using BaggageProperties =
21 std::vector<std::pair<std::string, std::optional<std::string>>>;
22
23class Baggage;
25
26/// @brief Baggage base exception
27class BaggageException : public std::runtime_error {
28 public:
29 explicit BaggageException(const std::string& message)
30 : std::runtime_error(message) {}
31};
32
33/// @brief property of entry. Has required key and optional value.
34/// Keys shouldn't contain '=', ';' and ','. Values shouldn't contains
35/// ',' and ';'
37 friend class BaggageEntry;
38
39 public:
40 BaggageEntryProperty(std::string_view key,
41 std::optional<std::string_view> value = std::nullopt);
42 std::string ToString() const;
43 std::optional<std::string> GetValue() const;
44 std::string GetKey() const;
45
46 private:
47 const std::string_view key_;
48 std::optional<std::string_view> value_;
49};
50
51/// @brief Baggage Entry. Has required key and value,
52/// optional list of properties.
53/// Keys shouldn't contain '=' and ','. Values shouldn't contains
54/// ',' and ';'
56 friend class Baggage;
57
58 public:
59 BaggageEntry(std::string_view key, std::string_view value,
60 std::vector<BaggageEntryProperty> properties);
61 std::string ToString() const;
62 std::string GetValue() const;
63 std::string GetKey() const;
64
65 /// @return vector of properties of chosen entry
67
68 /// @brief Check that entry contains property with selected key
69 bool HasProperty(const std::string& key) const;
70
71 /// @brief Get first property with selected key
72 /// @throws BaggageException If key doesn't exist
73 const BaggageEntryProperty& GetProperty(const std::string& key) const;
74
75 private:
76 /// @brief Add entry to the received header string
77 void ConcatenateWith(std::string& header) const;
78 const std::string_view key_;
79 std::string_view value_;
80 std::vector<BaggageEntryProperty> properties_;
81};
82
83/// @brief Baggage header. Contains entries (key, value, optional<properties>).
84///
85/// For more details on header check the official site
86/// https://w3c.github.io/baggage/
87///
88/// @see baggage::BaggageManagerComponent
89class Baggage {
90 public:
91 Baggage(std::string header, std::unordered_set<std::string> allowed_keys);
92 Baggage(const Baggage&) noexcept;
93 Baggage(Baggage&&) noexcept;
94
95 std::string ToString() const;
96
97 /// @return vector of entries
99
100 /// @brief check that header contains entry with selected key
101 bool HasEntry(const std::string& key) const;
102
103 /// @brief find first entry with selected key
104 /// @throws BaggageException If key doesn't exist
105 const BaggageEntry& GetEntry(const std::string& key) const;
106
107 /// @brief entry's key validation
108 bool IsValidEntry(const std::string& key) const;
109
110 /// @brief Add entry to baggage header.
111 /// @throws BaggageException If key, value or properties
112 /// don't match with requirements or if allowed_keys
113 /// don't contain selected key
114 void AddEntry(std::string key, std::string value,
115 BaggageProperties properties);
116
117 /// @brief get baggage allowed keys
119
120 protected:
121 /// @brief parsers
122 /// @returns std::nullopt If key, value or properties
123 /// don't match with requirements or if allowed_keys
124 /// don't contain selected key
125 std::optional<BaggageEntry> TryMakeBaggageEntry(std::string_view entry);
126 static std::optional<BaggageEntryProperty> TryMakeBaggageEntryProperty(
127 std::string_view property);
128
129 private:
130 /// @brief Parse baggage_header and fill entries_
131 void FillEntries();
132
133 /// @brief Create result_header
134 void CreateResultHeader();
135
136 std::string header_value_;
137 std::unordered_set<std::string> allowed_keys_;
138 std::vector<BaggageEntry> entries_;
139
140 // result header after parsing entities.
141 // empty string if is_valid_header == true
142 std::string result_header_;
143
144 // true if requested header == header for sending
145 bool is_valid_header_ = true;
146};
147
148/// @brief Parsing function
149std::optional<Baggage> TryMakeBaggage(
150 std::string header, std::unordered_set<std::string> allowed_keys);
151
152template <typename T>
153bool HasInvalidSymbols(const T& obj) {
154 return std::find_if(obj.begin(), obj.end(), [](unsigned char x) {
155 return x == ',' || x == ';' || x == '=' || std::isspace(x);
156 }) != obj.end();
157}
158
159inline engine::TaskInheritedVariable<Baggage> kInheritedBaggage;
160
161} // namespace baggage
162
163USERVER_NAMESPACE_END