userver: userver/server/http/http_request.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
http_request.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/server/http/http_request.hpp
4/// @brief @copybrief server::http::HttpRequest
5
6#include <chrono>
7#include <string>
8#include <vector>
9
10#include <userver/engine/task/task_processor_fwd.hpp>
11
12#include <userver/engine/io/sockaddr.hpp>
13#include <userver/server/http/form_data_arg.hpp>
14#include <userver/server/http/http_method.hpp>
15#include <userver/server/http/http_response.hpp>
16#include <userver/utils/datetime/wall_coarse_clock.hpp>
17#include <userver/utils/impl/internal_tag.hpp>
18#include <userver/utils/impl/transparent_hash.hpp>
19#include <userver/utils/str_icase.hpp>
20
21USERVER_NAMESPACE_BEGIN
22
23namespace server::handlers {
24class HttpRequestStatistics;
25class HttpHandlerBase;
26} // namespace server::handlers
27
28/// Server parts of the HTTP protocol implementation.
29namespace server::http {
30
31/// @brief HTTP Request data.
32/// @note do not create HttpRequest by hand in tests,
33/// use HttpRequestBuilder instead.
34class HttpRequest final {
35public:
36 using HeadersMap = USERVER_NAMESPACE::http::headers::HeaderMap;
37
38 using HeadersMapKeys = decltype(utils::impl::MakeKeysView(HeadersMap()));
39
40 using CookiesMap = std::unordered_map<std::string, std::string, utils::StrCaseHash>;
41
42 using CookiesMapKeys = decltype(utils::impl::MakeKeysView(CookiesMap()));
43
44 /// @cond
45 explicit HttpRequest(request::ResponseDataAccounter& data_accounter, utils::impl::InternalTag);
46 /// @endcond
47
48 HttpRequest(HttpRequest&&) = delete;
49 HttpRequest(const HttpRequest&) = delete;
50
51 ~HttpRequest();
52
53 /// @return HTTP method (e.g. GET/POST)
54 const HttpMethod& GetMethod() const;
55
56 /// @return HTTP method as a string (e.g. "GET")
57 const std::string& GetMethodStr() const;
58
59 /// @return Major version of HTTP. For example, for HTTP 1.0 it returns 1
60 int GetHttpMajor() const;
61
62 /// @return Minor version of HTTP. For example, for HTTP 1.0 it returns 0
63 int GetHttpMinor() const;
64
65 /// @brief Get HTTP request target as provided by the client (see
66 /// https://www.rfc-editor.org/rfc/rfc7230#section-5.3). May contain the whole URL, but usually it consists of path
67 /// and query string.
68 const std::string& GetUrl() const;
69
70 /// @brief Get the path part of HTTP request URL.
71 ///
72 /// Unlike @ref server::handlers::HandlerConfig::path, path parameters are not replaced with placeholders, this is
73 /// the original highly cardinal path.
74 const std::string& GetRequestPath() const;
75
76 /// @cond
77 std::chrono::duration<double> GetRequestTime() const;
78
79 std::chrono::duration<double> GetResponseTime() const;
80 /// @endcond
81
82 /// @return Host from the URL.
83 const std::string& GetHost() const;
84
85 /// @return Request remote (peer's) address
86 const engine::io::Sockaddr& GetRemoteAddress() const;
87
88 /// @return First argument value with name `arg_name` or an empty string if no
89 /// such argument.
90 /// Arguments are extracted from:
91 /// - query part of the URL,
92 /// - the HTTP body (only if `parse_args_from_body: true` for handler is set).
93 ///
94 /// In both cases, arg keys and values are url-decoded automatically when
95 /// parsing into the HttpRequest.
96 const std::string& GetArg(std::string_view arg_name) const;
97
98 /// @return Argument values with name `arg_name` or an empty vector if no
99 /// such argument.
100 /// Arguments are extracted from:
101 /// - query part of the URL,
102 /// - the HTTP body (only if `parse_args_from_body: true` for handler is set).
103 ///
104 /// In both cases, arg keys and values are url-decoded automatically when
105 /// parsing into the HttpRequest.
106 const std::vector<std::string>& GetArgVector(std::string_view arg_name) const;
107
108 /// @return true if argument with name arg_name exists, false otherwise.
109 /// Arguments are extracted from:
110 /// - query part of the URL,
111 /// - the HTTP body (only if `parse_args_from_body: true` for handler is set).
112 ///
113 /// In both cases, arg keys and values are url-decoded automatically when
114 /// parsing into the HttpRequest.
115 bool HasArg(std::string_view arg_name) const;
116
117 /// @return Count of arguments.
118 /// Arguments are extracted from:
119 /// - query part of the URL,
120 /// - the HTTP body (only if `parse_args_from_body: true` for handler is set).
121 size_t ArgCount() const;
122
123 /// @return List of names of arguments.
124 /// Arguments are extracted from:
125 /// - query part of the URL,
126 /// - the HTTP body (only if `parse_args_from_body: true` for handler is set).
127 std::vector<std::string> ArgNames() const;
128
129 /// @return First argument value with name arg_name from multipart/form-data
130 /// request or an empty FormDataArg if no such argument.
131 const FormDataArg& GetFormDataArg(std::string_view arg_name) const;
132
133 /// @return Argument values with name arg_name from multipart/form-data
134 /// request or an empty FormDataArg if no such argument.
135 const std::vector<FormDataArg>& GetFormDataArgVector(std::string_view arg_name) const;
136
137 /// @return true if argument with name arg_name exists in multipart/form-data
138 /// request, false otherwise.
139 bool HasFormDataArg(std::string_view arg_name) const;
140
141 /// @return Count of multipart/form-data arguments.
142 size_t FormDataArgCount() const;
143
144 /// @return List of names of multipart/form-data arguments.
145 std::vector<std::string> FormDataArgNames() const;
146
147 /// @return Named argument from URL path with wildcards.
148 /// @note Path args are currently NOT url-decoded automatically.
149 const std::string& GetPathArg(std::string_view arg_name) const;
150
151 /// @return Argument from URL path with wildcards by its 0-based index.
152 /// @note Path args are currently NOT url-decoded automatically.
153 const std::string& GetPathArg(size_t index) const;
154
155 /// @return true if named argument from URL path with wildcards exists, false
156 /// otherwise.
157 bool HasPathArg(std::string_view arg_name) const;
158
159 /// @return true if argument with index from URL path with wildcards exists,
160 /// false otherwise.
161 bool HasPathArg(size_t index) const;
162
163 /// @return Number of wildcard arguments in URL path.
164 size_t PathArgCount() const;
165
166 /// @return Value of the header with case insensitive name header_name, or an
167 /// empty string if no such header.
168 const std::string& GetHeader(std::string_view header_name) const;
169
170 /// @overload
171 const std::string& GetHeader(const USERVER_NAMESPACE::http::headers::PredefinedHeader& header_name) const;
172
173 /// @return true if header with case insensitive name header_name exists,
174 /// false otherwise.
175 bool HasHeader(std::string_view header_name) const;
176
177 /// @overload
178 bool HasHeader(const USERVER_NAMESPACE::http::headers::PredefinedHeader& header_name) const;
179
180 /// @return Number of headers.
181 size_t HeaderCount() const;
182
183 /// Removes the header with case insensitive name header_name.
184 void RemoveHeader(std::string_view header_name);
185
186 /// @overload
187 void RemoveHeader(const USERVER_NAMESPACE::http::headers::PredefinedHeader& header_name);
188
189 /// @return List of headers names.
190 HeadersMapKeys GetHeaderNames() const;
191
192 /// @return HTTP headers.
193 const HeadersMap& GetHeaders() const;
194
195 /// @return Value of the cookie with case sensitive name cookie_name, or an
196 /// empty string if no such cookie exists.
197 const std::string& GetCookie(const std::string& cookie_name) const;
198
199 /// @return true if cookie with case sensitive name cookie_name exists, false
200 /// otherwise.
201 bool HasCookie(const std::string& cookie_name) const;
202
203 /// @return Number of cookies.
204 size_t CookieCount() const;
205
206 /// @return List of cookies names.
207 CookiesMapKeys GetCookieNames() const;
208
209 /// @return HTTP cookies.
210 const CookiesMap& RequestCookies() const;
211
212 /// @return HTTP body.
213 const std::string& RequestBody() const;
214
215 /// @return moved out HTTP body. `this` is modified.
216 std::string ExtractRequestBody();
217
218 /// @cond
219 void SetRequestBody(std::string body);
220 void ParseArgsFromBody();
221 bool IsFinal() const;
222 /// @endcond
223
224 /// @brief Set the response status code.
225 ///
226 /// Equivalent to this->GetHttpResponse().SetStatus(status).
227 void SetResponseStatus(HttpStatus status) const;
228
229 /// @return true if the body of the request is still compressed. In other
230 /// words returns true if the static option `decompress_request` of a handler
231 /// was set to `false` and this is a compressed request.
232 bool IsBodyCompressed() const;
233
234 HttpResponse& GetHttpResponse() const;
235
236 /// Get approximate time point of request handling start
237 std::chrono::steady_clock::time_point GetStartTime() const;
238
239 /// @cond
240 void MarkAsInternalServerError() const;
241
242 void SetStartSendResponseTime();
243 void SetFinishSendResponseTime();
244
245 void WriteAccessLogs(
246 const logging::TextLoggerPtr& logger_access,
247 const logging::TextLoggerPtr& logger_access_tskv,
248 const std::string& remote_address
249 ) const;
250
251 void WriteAccessLog(
252 const logging::TextLoggerPtr& logger_access,
253 utils::datetime::WallCoarseClock::time_point tp,
254 const std::string& remote_address
255 ) const;
256
257 void WriteAccessTskvLog(
258 const logging::TextLoggerPtr& logger_access_tskv,
259 utils::datetime::WallCoarseClock::time_point tp,
260 const std::string& remote_address
261 ) const;
262
263 using UpgradeCallback = std::function<void(std::unique_ptr<engine::io::RwBase>&&, engine::io::Sockaddr&&)>;
264
265 bool IsUpgradeWebsocket() const;
266 void SetUpgradeWebsocket(UpgradeCallback cb) const;
267 void DoUpgrade(std::unique_ptr<engine::io::RwBase>&& socket, engine::io::Sockaddr&& peer_name) const;
268 /// @endcond
269
270private:
271 void AccountResponseTime();
272
273 void SetPathArgs(std::vector<std::pair<std::string, std::string>> args);
274
275 void SetHttpHandler(const handlers::HttpHandlerBase& handler);
276 const handlers::HttpHandlerBase* GetHttpHandler() const;
277
278 void SetTaskProcessor(engine::TaskProcessor& task_processor);
279 engine::TaskProcessor* GetTaskProcessor() const;
280
281 void SetHttpHandlerStatistics(handlers::HttpRequestStatistics&);
282
283 // HTTP/2.0 only
284 void SetResponseStreamId(std::int32_t);
285 void SetStreamProducer(impl::Http2StreamEventProducer&& producer);
286
287 void SetTaskCreateTime();
288 void SetTaskStartTime();
289 void SetResponseNotifyTime();
290 void SetResponseNotifyTime(std::chrono::steady_clock::time_point now);
291
292 friend class HttpRequestBuilder;
293 friend class HttpRequestHandler;
294
295 struct Impl;
296 utils::FastPimpl<Impl, 1648, 16> pimpl_;
297};
298
299} // namespace server::http
300
301USERVER_NAMESPACE_END