userver: userver/server/http/http_request.hpp Source File
Loading...
Searching...
No Matches
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 /// @return Request URL
66 const std::string& GetUrl() const;
67
68 /// @return Request path
69 const std::string& GetRequestPath() const;
70
71 /// @cond
72 std::chrono::duration<double> GetRequestTime() const;
73
74 std::chrono::duration<double> GetResponseTime() const;
75 /// @endcond
76
77 /// @return Host from the URL.
78 const std::string& GetHost() const;
79
80 /// @return Request remote (peer's) address
81 const engine::io::Sockaddr& GetRemoteAddress() const;
82
83 /// @return First argument value with name `arg_name` or an empty string if no
84 /// such argument.
85 /// Arguments are extracted from:
86 /// - query part of the URL,
87 /// - the HTTP body (only if `parse_args_from_body: true` for handler is set).
88 ///
89 /// In both cases, arg keys and values are url-decoded automatically when
90 /// parsing into the HttpRequest.
91 const std::string& GetArg(std::string_view arg_name) const;
92
93 /// @return Argument values with name `arg_name` or an empty vector if no
94 /// such argument.
95 /// Arguments are extracted from:
96 /// - query part of the URL,
97 /// - the HTTP body (only if `parse_args_from_body: true` for handler is set).
98 ///
99 /// In both cases, arg keys and values are url-decoded automatically when
100 /// parsing into the HttpRequest.
102
103 /// @return true if argument with name arg_name exists, false otherwise.
104 /// Arguments are extracted from:
105 /// - query part of the URL,
106 /// - the HTTP body (only if `parse_args_from_body: true` for handler is set).
107 ///
108 /// In both cases, arg keys and values are url-decoded automatically when
109 /// parsing into the HttpRequest.
110 bool HasArg(std::string_view arg_name) const;
111
112 /// @return Count of arguments.
113 /// Arguments are extracted from:
114 /// - query part of the URL,
115 /// - the HTTP body (only if `parse_args_from_body: true` for handler is set).
117
118 /// @return List of names of arguments.
119 /// Arguments are extracted from:
120 /// - query part of the URL,
121 /// - the HTTP body (only if `parse_args_from_body: true` for handler is set).
123
124 /// @return First argument value with name arg_name from multipart/form-data
125 /// request or an empty FormDataArg if no such argument.
127
128 /// @return Argument values with name arg_name from multipart/form-data
129 /// request or an empty FormDataArg if no such argument.
131
132 /// @return true if argument with name arg_name exists in multipart/form-data
133 /// request, false otherwise.
134 bool HasFormDataArg(std::string_view arg_name) const;
135
136 /// @return Count of multipart/form-data arguments.
138
139 /// @return List of names of multipart/form-data arguments.
141
142 /// @return Named argument from URL path with wildcards.
143 /// @note Path args are currently NOT url-decoded automatically.
144 const std::string& GetPathArg(std::string_view arg_name) const;
145
146 /// @return Argument from URL path with wildcards by its 0-based index.
147 /// @note Path args are currently NOT url-decoded automatically.
148 const std::string& GetPathArg(size_t index) const;
149
150 /// @return true if named argument from URL path with wildcards exists, false
151 /// otherwise.
152 bool HasPathArg(std::string_view arg_name) const;
153
154 /// @return true if argument with index from URL path with wildcards exists,
155 /// false otherwise.
156 bool HasPathArg(size_t index) const;
157
158 /// @return Number of wildcard arguments in URL path.
160
161 /// @return Value of the header with case insensitive name header_name, or an
162 /// empty string if no such header.
163 const std::string& GetHeader(std::string_view header_name) const;
164
165 /// @overload
166 const std::string& GetHeader(const USERVER_NAMESPACE::http::headers::PredefinedHeader& header_name) const;
167
168 /// @return true if header with case insensitive name header_name exists,
169 /// false otherwise.
170 bool HasHeader(std::string_view header_name) const;
171
172 /// @overload
173 bool HasHeader(const USERVER_NAMESPACE::http::headers::PredefinedHeader& header_name) const;
174
175 /// @return Number of headers.
177
178 /// Removes the header with case insensitive name header_name.
179 void RemoveHeader(std::string_view header_name);
180
181 /// @overload
182 void RemoveHeader(const USERVER_NAMESPACE::http::headers::PredefinedHeader& header_name);
183
184 /// @return List of headers names.
186
187 /// @return HTTP headers.
188 const HeadersMap& GetHeaders() const;
189
190 /// @return Value of the cookie with case sensitive name cookie_name, or an
191 /// empty string if no such cookie exists.
192 const std::string& GetCookie(const std::string& cookie_name) const;
193
194 /// @return true if cookie with case sensitive name cookie_name exists, false
195 /// otherwise.
196 bool HasCookie(const std::string& cookie_name) const;
197
198 /// @return Number of cookies.
200
201 /// @return List of cookies names.
203
204 /// @return HTTP cookies.
206
207 /// @return HTTP body.
208 const std::string& RequestBody() const;
209
210 /// @return moved out HTTP body. `this` is modified.
211 std::string ExtractRequestBody();
212
213 /// @cond
214 void SetRequestBody(std::string body);
215 void ParseArgsFromBody();
216 bool IsFinal() const;
217 /// @endcond
218
219 /// @brief Set the response status code.
220 ///
221 /// Equivalent to this->GetHttpResponse().SetStatus(status).
222 void SetResponseStatus(HttpStatus status) const;
223
224 /// @return true if the body of the request is still compressed. In other
225 /// words returns true if the static option `decompress_request` of a handler
226 /// was set to `false` and this is a compressed request.
227 bool IsBodyCompressed() const;
228
229 HttpResponse& GetHttpResponse() const;
230
231 /// Get approximate time point of request handling start
232 std::chrono::steady_clock::time_point GetStartTime() const;
233
234 /// @cond
235 void MarkAsInternalServerError() const;
236
237 void SetStartSendResponseTime();
238 void SetFinishSendResponseTime();
239
240 void WriteAccessLogs(
241 const logging::LoggerPtr& logger_access,
242 const logging::LoggerPtr& logger_access_tskv,
243 const std::string& remote_address
244 ) const;
245
246 void WriteAccessLog(
247 const logging::LoggerPtr& logger_access,
248 utils::datetime::WallCoarseClock::time_point tp,
249 const std::string& remote_address
250 ) const;
251
252 void WriteAccessTskvLog(
253 const logging::LoggerPtr& logger_access_tskv,
254 utils::datetime::WallCoarseClock::time_point tp,
255 const std::string& remote_address
256 ) const;
257
258 using UpgradeCallback = std::function<void(std::unique_ptr<engine::io::RwBase>&&, engine::io::Sockaddr&&)>;
259
260 bool IsUpgradeWebsocket() const;
261 void SetUpgradeWebsocket(UpgradeCallback cb) const;
262 void DoUpgrade(std::unique_ptr<engine::io::RwBase>&& socket, engine::io::Sockaddr&& peer_name) const;
263 /// @endcond
264
265private:
266 void AccountResponseTime();
267
268 void SetPathArgs(std::vector<std::pair<std::string, std::string>> args);
269
270 void SetHttpHandler(const handlers::HttpHandlerBase& handler);
271 const handlers::HttpHandlerBase* GetHttpHandler() const;
272
273 void SetTaskProcessor(engine::TaskProcessor& task_processor);
274 engine::TaskProcessor* GetTaskProcessor() const;
275
276 void SetHttpHandlerStatistics(handlers::HttpRequestStatistics&);
277
278 // HTTP/2.0 only
279 void SetResponseStreamId(std::int32_t);
280 void SetStreamProducer(impl::Http2StreamEventProducer&& producer);
281
282 void SetTaskCreateTime();
283 void SetTaskStartTime();
284 void SetResponseNotifyTime();
285 void SetResponseNotifyTime(std::chrono::steady_clock::time_point now);
286
287 friend class HttpRequestBuilder;
288 friend class HttpRequestHandler;
289
290 struct Impl;
291 utils::FastPimpl<Impl, 1648, 16> pimpl_;
292};
293
294} // namespace server::http
295
296USERVER_NAMESPACE_END