userver: userver/server/request/request_context.hpp Source File
Loading...
Searching...
No Matches
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