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