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