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