userver: userver/server/request/request_context.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
request_context.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/server/request/request_context.hpp
4/// @brief @copybrief server::request::RequestContext
5
6#include <string>
7
8#include <userver/compiler/select.hpp>
9#include <userver/utils/any_movable.hpp>
10#include <userver/utils/fast_pimpl.hpp>
11
12USERVER_NAMESPACE_BEGIN
13
14namespace server::request {
15
16/// @brief Stores request-specific data during request processing.
17///
18/// For example: you can store some data in `HandleRequestThrow()` method
19/// and access this data in `GetResponseDataForLogging()` method.
20class RequestContext final {
21 public:
22 RequestContext();
23
24 RequestContext(RequestContext&&) noexcept;
25
26 RequestContext(const RequestContext&) = delete;
27
28 ~RequestContext();
29
30 /// @brief Stores user data if it was not previously stored in this.
31 /// @throw std::runtime_error if user data was already stored.
32 template <typename Data>
33 Data& SetUserData(Data data);
34
35 /// @brief Emplaces user data if it was not previously stored in this.
36 /// @throw std::runtime_error if user data was already stored.
37 template <typename Data, typename... Args>
38 Data& EmplaceUserData(Args&&... args);
39
40 /// @returns Stored user data
41 /// @throws std::runtime_error if no data was stored
42 /// @throws std::bad_any_cast if data of different type was stored
43 template <typename Data>
44 Data& GetUserData();
45
46 /// @returns Stored user data
47 /// @throws std::runtime_error if no data was stored
48 /// @throws std::bad_any_cast if data of different type was stored
49 template <typename Data>
50 const Data& GetUserData() const;
51
52 /// @returns A pointer to data of type Data if it was stored before during
53 /// current request processing or nullptr otherwise
54 template <typename Data>
56
57 /// @returns A pointer to data of type Data if it was stored before during
58 /// current request processing or nullptr otherwise
59 template <typename Data>
61
62 /// @brief Erases the user data.
63 void EraseUserData();
64
65 /// @brief Stores the data with specified name if it was not previously stored
66 /// in this.
67 /// @throw std::runtime_error if data with such name was already stored.
68 template <typename Data>
69 Data& SetData(std::string name, Data data);
70
71 /// @brief Emplaces the data with specified name if it was not previously
72 /// stored in this.
73 /// @throw std::runtime_error if data with such name was already stored.
74 template <typename Data, typename... Args>
75 Data& EmplaceData(std::string name, Args&&... args);
76
77 /// @returns Stored data with specified name.
78 /// @throws std::runtime_error if no data was stored
79 /// @throws std::bad_any_cast if data of different type was stored
80 template <typename Data>
81 Data& GetData(const std::string& name);
82
83 /// @returns Stored data with specified name.
84 /// @throws std::runtime_error if no data was stored
85 /// @throws std::bad_any_cast if data of different type was stored
86 template <typename Data>
87 const Data& GetData(const std::string& name) const;
88
89 /// @returns Stored data with specified name or nullptr if no data found.
90 /// @throws std::bad_any_cast if data of different type was stored.
91 template <typename Data>
93
94 /// @returns Stored data with specified name or nullptr if no data found.
95 /// @throws std::bad_any_cast if data of different type was stored.
96 template <typename Data>
98 const std::string& name) const;
99
100 /// @brief Erase data with specified name.
101 void EraseData(const std::string& name);
102
103 private:
104 class Impl;
105
106 static constexpr std::size_t kPimplSize = compiler::SelectSize() //
107 .ForLibCpp32(24)
108 .ForLibCpp64(48)
109 .ForLibStdCpp64(64)
110 .ForLibStdCpp32(32);
111
112 utils::AnyMovable& SetUserAnyData(utils::AnyMovable&& data);
113 utils::AnyMovable& GetUserAnyData();
114 utils::AnyMovable* GetUserAnyDataOptional();
115 void EraseUserAnyData();
116
117 utils::AnyMovable& SetAnyData(std::string&& name, utils::AnyMovable&& data);
118 utils::AnyMovable& GetAnyData(const std::string& name);
119 utils::AnyMovable* GetAnyDataOptional(const std::string& name);
120 void EraseAnyData(const std::string& name);
121
122 utils::FastPimpl<Impl, kPimplSize, alignof(void*), utils::kStrictMatch> impl_;
123};
124
125template <typename Data>
126Data& RequestContext::SetUserData(Data data) {
127 return utils::AnyCast<Data&>(SetUserAnyData(std::move(data)));
128}
129
130template <typename Data, typename... Args>
131Data& RequestContext::EmplaceUserData(Args&&... args) {
132 return utils::AnyCast<Data&>(
133 SetUserAnyData(Data(std::forward<Args>(args)...)));
134}
135
136template <typename Data>
137Data& RequestContext::GetUserData() {
138 return utils::AnyCast<Data&>(GetUserAnyData());
139}
140
141template <typename Data>
142const Data& RequestContext::GetUserData() const {
143 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
144 return const_cast<RequestContext*>(this)->GetUserData<Data>();
145}
146
147template <typename Data>
149 auto* data = GetUserAnyDataOptional();
150 return data ? &utils::AnyCast<Data&>(*data) : nullptr;
151}
152
153template <typename Data>
155 const {
156 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
157 return const_cast<RequestContext*>(this)->GetUserDataOptional<Data>();
158}
159
160inline void RequestContext::EraseUserData() { EraseUserAnyData(); }
161
162template <typename Data>
163Data& RequestContext::SetData(std::string name, Data data) {
164 return utils::AnyCast<Data&>(SetAnyData(std::move(name), std::move(data)));
165}
166
167template <typename Data, typename... Args>
168Data& RequestContext::EmplaceData(std::string name, Args&&... args) {
169 return utils::AnyCast<Data&>(
170 SetAnyData(std::move(name), Data(std::forward<Args>(args)...)));
171}
172
173template <typename Data>
174Data& RequestContext::GetData(const std::string& name) {
175 return utils::AnyCast<Data&>(GetAnyData(name));
176}
177
178template <typename Data>
179const Data& RequestContext::GetData(const std::string& name) const {
180 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
181 return const_cast<RequestContext*>(this)->GetData<Data>(name);
182}
183
184template <typename Data>
186 const std::string& name) {
187 auto* data = GetAnyDataOptional(name);
188 return data ? &utils::AnyCast<Data&>(*data) : nullptr;
189}
190
191template <typename Data>
193 const std::string& name) const {
194 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
195 return const_cast<RequestContext*>(this)->GetDataOptional<Data>(name);
196}
197
198inline void RequestContext::EraseData(const std::string& name) {
199 EraseAnyData(name);
200}
201
202} // namespace server::request
203
204USERVER_NAMESPACE_END