userver: userver/clients/http/request.hpp Source File
Loading...
Searching...
No Matches
request.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/clients/http/request.hpp
4/// @brief @copybrief clients::http::Request
5
6#include <memory>
7#include <string_view>
8#include <vector>
9
10#include <userver/clients/dns/resolver_fwd.hpp>
11#include <userver/clients/http/error.hpp>
12#include <userver/clients/http/response.hpp>
13#include <userver/clients/http/response_future.hpp>
14#include <userver/concurrent/queue.hpp>
15#include <userver/crypto/certificate.hpp>
16#include <userver/crypto/private_key.hpp>
17#include <userver/http/http_version.hpp>
18#include <userver/utils/impl/internal_tag_fwd.hpp>
19#include <userver/utils/impl/source_location.hpp>
20#include <userver/utils/not_null.hpp>
21
22USERVER_NAMESPACE_BEGIN
23
24namespace tracing {
26} // namespace tracing
27
28namespace utils::impl {
29class WaitTokenStorageLock;
30} // namespace utils::impl
31
32/// HTTP client helpers
33namespace clients::http {
34
35class RequestState;
36class StreamedResponse;
37class WebSocketResponse;
38class ConnectTo;
39class Form;
41class RequestStats;
42class DestinationStatistics;
43struct TestsuiteConfig;
44class MiddlewareBase;
45
46namespace impl {
47class EasyWrapper;
48} // namespace impl
49
50/// @brief HTTP request method
51enum class HttpMethod { kGet, kPost, kHead, kPut, kDelete, kPatch, kOptions };
52
53/// @brief Convert HTTP method enum value to string
54std::string_view ToStringView(HttpMethod method);
55
56/// @brief Convert HTTP method string to enum value
57HttpMethod HttpMethodFromString(std::string_view method_str);
58
59using USERVER_NAMESPACE::http::HttpVersion;
60
61/// HTTP Authorization types
62enum class HttpAuthType {
63 kBasic, ///< "basic"
64 kDigest, ///< "digest"
65 kDigestIE, ///< "digest_ie"
66 kNegotiate, ///< "negotiate"
67 kNtlm, ///< "ntlm"
68 kNtlmWb, ///< "ntlm_wb"
69 kAny, ///< "any"
70 kAnySafe, ///< "any_safe"
71};
72
73/// HTTP Proxy Authorization types
74enum class ProxyAuthType {
75 kBasic, ///< "basic"
76 kDigest, ///< "digest"
77 kDigestIE, ///< "digest_ie"
78 kBearer, ///< "bearer"
79 kNegotiate, ///< "negotiate"
80 kNtlm, ///< "ntlm"
81 kNtlmWb, ///< "ntlm_wb"
82 kAny, ///< "any"
83 kAnySafe, ///< "any_safe"
84};
85
86ProxyAuthType ProxyAuthTypeFromString(std::string_view auth_name);
87
88/// @brief Class for creating and performing new http requests, usually retrieved from @ref clients::http::Client.
89class Request final {
90public:
91 /// Request cookies container type
92 using Cookies = std::unordered_map<std::string, std::string, utils::StrCaseHash>;
93
94 /// @cond
95 // For internal use only.
96 explicit Request(
97 impl::EasyWrapper&&,
98 RequestStats&& req_stats,
99 const std::shared_ptr<DestinationStatistics>& dest_stats,
100 clients::dns::Resolver* resolver,
101 const tracing::TracingManagerBase& tracing_manager
102 );
103 /// @endcond
104
105 /// Specifies method
106 Request& method(HttpMethod method) &;
107 /// @overload
108 Request method(HttpMethod method) &&;
109
110 /// GET request
111 Request& get() &;
112 /// @overload
113 Request get() &&;
114 /// @overload
115 Request& get(std::string url) &;
116 /// @overload
117 Request get(std::string url) &&;
118
119 /// HEAD request
120 Request& head() &;
121 /// @overload
122 Request head() &&;
123 /// @overload
124 Request& head(std::string url) &;
125 /// @overload
126 Request head(std::string url) &&;
127
128 /// POST request
129 Request& post() &;
130 /// @overload
131 Request post() &&;
132 /// @overload
133 Request& post(std::string url, std::string data = {}) &;
134 /// @overload
135 Request post(std::string url, std::string data = {}) &&;
136 /// @overload
137 Request& post(std::string url, Form&& form) &;
138 /// @overload
139 Request post(std::string url, Form&& form) &&;
140
141 /// PUT request
142 Request& put() &;
143 /// @overload
144 Request put() &&;
145 /// @overload
146 Request& put(std::string url, std::string data = {}) &;
147 /// @overload
148 Request put(std::string url, std::string data = {}) &&;
149
150 /// PATCH request
151 Request& patch() &;
152 /// @overload
153 Request patch() &&;
154 /// @overload
155 Request& patch(std::string url, std::string data = {}) &;
156 /// @overload
157 Request patch(std::string url, std::string data = {}) &&;
158
159 /// DELETE request
160 Request& delete_method() &;
161 /// @overload
162 Request delete_method() &&;
163 /// @overload
164 Request& delete_method(std::string url) &;
165 /// @overload
166 Request delete_method(std::string url) &&;
167 /// @overload
168 Request& delete_method(std::string url, std::string data) &;
169 /// @overload
170 Request delete_method(std::string url, std::string data) &&;
171
172 /// Set custom request method. Only replaces name of the HTTP method
173 Request& set_custom_http_request_method(std::string method) &;
174 /// @overload
175 Request set_custom_http_request_method(std::string method) &&;
176
177 /// url if you don't specify request type with url
178 Request& url(std::string url) &;
179 /// @overload
180 Request url(std::string url) &&;
181
182 /// Set data for POST request
183 Request& data(std::string data) &;
184 /// @overload
185 Request data(std::string data) &&;
186
187 /// Set 'form' for POST request
188 Request& form(Form&& form) &;
189 /// @overload
190 Request form(Form&& form) &&;
191
192 /// Set headers for request
193 Request& headers(const Headers& headers) &;
194 /// @overload
195 Request headers(const Headers& headers) &&;
196 /// @overload
197 Request& headers(const std::initializer_list<std::pair<utils::zstring_view, utils::zstring_view>>& headers) &;
198 /// @overload
199 Request headers(const std::initializer_list<std::pair<utils::zstring_view, utils::zstring_view>>& headers) &&;
200
201 /// Sets http auth type to use.
203 HttpAuthType value,
204 bool auth_only,
205 utils::zstring_view user,
206 utils::zstring_view password
207 ) &;
208 /// @overload
210 HttpAuthType value,
211 bool auth_only,
212 utils::zstring_view user,
213 utils::zstring_view password
214 ) &&;
215
216 /// Set proxy headers for request
217 Request& proxy_headers(const Headers& headers) &;
218 /// @overload
219 Request proxy_headers(const Headers& headers) &&;
220 /// @overload
221 Request& proxy_headers(const std::initializer_list<std::pair<utils::zstring_view, utils::zstring_view>>& headers) &;
222 /// @overload
223 Request proxy_headers(const std::initializer_list<std::pair<utils::zstring_view, utils::zstring_view>>& headers) &&;
224
225 /// Sets the User-Agent header
226 Request& user_agent(utils::zstring_view value) &;
227 /// @overload
228 Request user_agent(utils::zstring_view value) &&;
229
230 /// Sets proxy to use.
231 ///
232 /// Example: [::1]:1080
233 /// Empty string disables proxy.
234 Request& proxy(utils::zstring_view value) &;
235 /// @overload
236 Request proxy(utils::zstring_view value) &&;
237
238 /// Sets proxy auth type to use.
240 /// @overload
242
243 /// Cookies for request as HashDos-safe map
244 Request& cookies(const Cookies& cookies) &;
245 /// Cookies for request as HashDos-safe map
246 Request cookies(const Cookies& cookies) &&;
247
248 /// Cookies for request as map
249 Request& cookies(const std::unordered_map<std::string, std::string>& cookies) &;
250 /// Cookies for request as map
251 Request cookies(const std::unordered_map<std::string, std::string>& cookies) &&;
252
253 /// Follow redirects or not. Default: follow
254 Request& follow_redirects(bool follow = true) &;
255 /// @overload
256 Request follow_redirects(bool follow = true) &&;
257
258 /// The maximum time in milliseconds for the entire transfer operation (from name lookup and connection
259 /// construction to the end of data acquisition).
260 Request& timeout(long timeout_ms) &;
261 /// @overload
262 Request timeout(long timeout_ms) &&;
263 /// @overload
264 Request& timeout(std::chrono::milliseconds timeout_ms) & { return timeout(timeout_ms.count()); }
265 /// @overload
266 Request timeout(std::chrono::milliseconds timeout_ms) && { return std::move(this->timeout(timeout_ms.count())); }
267
268 /// Verify host and peer or not. Default: verify
269 Request& verify(bool verify = true) &;
270 /// @overload
271 Request verify(bool verify = true) &&;
272
273 /// Set file holding one or more certificates to verify the peer with
274 Request& ca_info(utils::zstring_view file_path) &;
275 /// @overload
276 Request ca_info(utils::zstring_view file_path) &&;
277
278 /// Set CA
279 Request& ca(crypto::Certificate cert) &;
280 /// @overload
281 Request ca(crypto::Certificate cert) &&;
282
283 /// Set CRL-file
284 Request& crl_file(utils::zstring_view file_path) &;
285 /// @overload
286 Request crl_file(utils::zstring_view file_path) &&;
287
288 /// Set private client key and certificate for request.
289 ///
290 /// @warning Do not use this function on MacOS as it may cause Segmentation Fault on that platform.
291 Request& client_key_cert(crypto::PrivateKey pkey, crypto::Certificate cert) &;
292 /// @overload
293 Request client_key_cert(crypto::PrivateKey pkey, crypto::Certificate cert) &&;
294
295 /// Set HTTP version
296 Request& http_version(HttpVersion version) &;
297 /// @overload
298 Request http_version(HttpVersion version) &&;
299
300 /// Specify number of retries on incorrect status, if on_fails is True
301 /// retry on network error too. Retries = 3 means that maximum 3 request will be performed.
302 ///
303 /// Retries use exponential backoff with jitter - an exponentially increasing
304 /// randomized delay is added before each retry of this request.
305 Request& retry(short retries = 3, bool on_fails = true) &;
306 Request retry(short retries = 3, bool on_fails = true) &&;
307
308 /// Set unix domain socket as connection endpoint and provide path to it
309 /// When enabled, request will connect to the Unix domain socket instead
310 /// of establishing a TCP connection to a host.
312 Request unix_socket_path(utils::zstring_view path) &&;
313
314 /// Set CURL_IPRESOLVE_V4 for ipv4 resolving
315 Request& use_ipv4() &;
316 /// @overload
317 Request use_ipv4() &&;
318
319 /// Set CURL_IPRESOLVE_V6 for ipv6 resolving
320 Request& use_ipv6() &;
321 /// @overload
322 Request use_ipv6() &&;
323
324 /// Set CURLOPT_CONNECT_TO option
325 /// @warning connect_to argument must outlive Request
326 Request& connect_to(const ConnectTo& connect_to) &;
327 /// @overload
328 Request connect_to(const ConnectTo& connect_to) &&;
329
330 /// @overload
331 template <typename T>
332 std::enable_if_t<std::is_same_v<ConnectTo, T>, Request&> connect_to(T&&) {
333 static_assert(!sizeof(T), "ConnectTo argument must not be temporary, it must outlive Request");
334 return *this;
335 }
336
337 /// Override list of middlewares from @ref components::HttpClient for specific request
338 Request& SetMiddlewaresList(const std::vector<utils::NotNull<MiddlewareBase*>>& middlewares) &;
339
340 /// Set flag to ignore tls receive error for responses
341 /// with `Connection: close` header.
342 ///
343 /// The behaviour of handling TLS errors has been changed
344 /// in libcurl>=8.15.0 and reproducible for connections
345 /// with incomplete TLS close procedure.
346 ///
347 /// @see https://github.com/curl/curl/pull/17531/changes
349 /// @overload
351
352 /// Override log URL. Useful for "there's a secret in the query".
353 /// @warning The query might be logged by other intermediate HTTP agents (nginx, L7 balancer, etc.).
354 Request& SetLoggedUrl(std::string url) &;
355 /// @overload
356 Request SetLoggedUrl(std::string url) &&;
357
358 /// Set URL template (low-cardinality) for tracing, i.e. `/v1/user/{user_id}`
359 /// @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/url/
360 Request& SetUrlTemplate(std::string url_template) &;
361 /// @overload
362 Request SetUrlTemplate(std::string url_template) &&;
363
364 /// Set destination name in metric "httpclient.destinations.<name>".
365 /// If not set, defaults to HTTP path. Should be called for all requests
366 /// with parameters in HTTP path.
367 Request& SetDestinationMetricName(const std::string& destination) &;
368 /// @overload
369 Request SetDestinationMetricName(const std::string& destination) &&;
370
371 /// @cond
372 // Set testsuite related settings. For internal use only.
373 void SetTestsuiteConfig(const std::shared_ptr<const TestsuiteConfig>& config) &;
374
375 void SetAllowedUrlsExtra(const std::vector<std::string>& urls) &;
376
377 // Set deadline propagation settings. For internal use only.
378 void SetDeadlinePropagationConfig(const DeadlinePropagationConfig& deadline_propagation_config) &;
379
380 void SetWaitToken(utils::impl::InternalTag, utils::impl::WaitTokenStorageLock&&);
381 /// @endcond
382
383 /// Disable auto-decoding of received replies. Useful to proxy replies 'as is'.
385 /// @overload
387
388 void SetCancellationPolicy(CancellationPolicy cp);
389
390 /// Override the default tracing manager from HTTP client for this particular request.
392 /// @overload
394
395 /// Perform request asynchronously.
396 ///
397 /// Works well with @ref engine::WaitAny(), @ref engine::WaitAnyFor(), and @ref engine::WaitUntil() functions:
398 /// @snippet src/clients/http/client_wait_test.cpp HTTP Client - waitany
399 ///
400 /// Refrain from reusing the Request object.
401 /// Though it might be possible to reuse it after extracting data from ResponseFuture, a subsequent async_perform
402 /// or perform call could be delayed until the previous request fully completes. This delay can occur if the
403 /// previous request either timed out or was canceled.
404 /// Future versions might entirely forbid Request objects reuse.
405 [[nodiscard]] ResponseFuture async_perform(
406 utils::impl::SourceLocation location = utils::impl::SourceLocation::Current()
407 );
408
409 /// @brief Perform a request with streamed response body.
410 ///
411 /// The HTTP client uses queue producer. StreamedResponse uses queue consumer.
412 [[nodiscard]] StreamedResponse async_perform_stream_body(
413 const std::shared_ptr<concurrent::StringStreamQueue>& queue,
414 utils::impl::SourceLocation location = utils::impl::SourceLocation::Current()
415 );
416
417 /// Calls async_perform and wait for timeout_ms on a future. Default time for waiting will be timeout value if it
418 /// was set. If error occurred it will be thrown as exception.
419 ///
420 /// Refrain from reusing the Request object.
421 /// Though it might be possible to reuse it after extracting data from ResponseFuture, a subsequent async_perform
422 /// or perform call could be delayed until the previous request fully completes. This delay can occur if the
423 /// previous request either timed out or was canceled.
424 /// Future versions might entirely forbid Request objects reuse.
425 [[nodiscard]] std::shared_ptr<Response> perform(
426 utils::impl::SourceLocation location = utils::impl::SourceLocation::Current()
427 );
428
429 /// @brief Starts the Websocket handshake.
430 ///
431 /// @snippet samples/websocket_client/main.cpp WebSocket client sample - handler
432 [[nodiscard]] WebSocketResponse PerformWebSocketHandshake(
433 utils::impl::SourceLocation location = utils::impl::SourceLocation::Current()
434 );
435
436 /// Returns a reference to the original URL of a request
437 const std::string& GetUrl() const&;
438 /// @overload
439 const std::string& GetUrl() && = delete;
440
441 /// Returns a reference to the HTTP body of a request to send
442 const std::string& GetData() const&;
443 /// @overload
444 const std::string& GetData() && = delete;
445
446 /// Returns HTTP body of a request, leaving it empty
447 std::string ExtractData();
448
449private:
450 std::shared_ptr<RequestState> pimpl_;
451};
452
453} // namespace clients::http
454
455USERVER_NAMESPACE_END