Kurlyk
Loading...
Searching...
No Matches
utils.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _KURLYK_HTTP_UTILS_HPP_INCLUDED
3#define _KURLYK_HTTP_UTILS_HPP_INCLUDED
4
9
10namespace kurlyk {
11
18 inline HttpRateLimitHandlePtr create_rate_limit(long requests_per_period, long period_ms, bool sequential = false) {
19 return HttpRequestManager::get_instance().create_rate_limit(requests_per_period, period_ms, sequential);
20 }
21
27 inline HttpRateLimitHandlePtr create_rate_limit_rpm(long requests_per_minute, bool sequential = false) {
28 long period_ms = 60000; // 1 minute in milliseconds
29 return HttpRequestManager::get_instance().create_rate_limit(requests_per_minute, period_ms, sequential);
30 }
31
37 inline HttpRateLimitHandlePtr create_rate_limit_rps(long requests_per_second, bool sequential = false) {
38 long period_ms = 1000; // 1 second in milliseconds
39 return HttpRequestManager::get_instance().create_rate_limit(requests_per_second, period_ms, sequential);
40 }
41
44 inline HttpRateLimitHandlePtr get_rate_limit(long limit_id) {
46 }
47
52 inline bool remove_limit(long limit_id) {
54 }
55
59 inline bool remove_limit(const HttpRateLimitHandlePtr& limit) {
61 }
62
68
74
80
86
90 inline void cancel_request_by_id(uint64_t request_id, std::function<void()> callback) {
91 HttpRequestManager::get_instance().cancel_request_by_id(request_id, std::move(callback));
93 }
94
98 inline std::future<void> cancel_request_by_id(uint64_t request_id) {
99 auto promise = std::make_shared<std::promise<void>>();
100 auto future = promise->get_future();
102 try {
103 promise->set_value();
104 } catch (const std::future_error& e) {
105 if (e.code() == std::make_error_condition(std::future_errc::promise_already_satisfied)) {
106 KURLYK_HANDLE_ERROR(e, "Promise already satisfied in HttpClient::request callback");
107 } else {
108 KURLYK_HANDLE_ERROR(e, "Future error in HttpClient::request callback");
109 }
110 } catch (const std::exception& e) {
111 KURLYK_HANDLE_ERROR(e, "Unhandled exception in HttpClient::request callback");
112 } catch (...) {
113 // Unknown fatal error in request callback
114 }
115 });
117 return future;
118 }
119
123 inline void cancel_requests_by_group_id(uint64_t group_id, std::function<void()> callback) {
124 HttpRequestManager::get_instance().cancel_requests_by_group_id(group_id, std::move(callback));
126 }
127
131 inline std::future<void> cancel_requests_by_group_id(uint64_t group_id) {
132 auto promise = std::make_shared<std::promise<void>>();
133 auto future = promise->get_future();
135 try {
136 promise->set_value();
137 } catch (const std::future_error& e) {
138 if (e.code() == std::make_error_condition(std::future_errc::promise_already_satisfied)) {
139 KURLYK_HANDLE_ERROR(e, "Promise already satisfied in HttpClient::request callback");
140 } else {
141 KURLYK_HANDLE_ERROR(e, "Future error in HttpClient::request callback");
142 }
143 } catch (const std::exception& e) {
144 KURLYK_HANDLE_ERROR(e, "Unhandled exception in HttpClient::request callback");
145 } catch (...) {
146 // Unknown fatal error in request callback
147 }
148 });
150 return future;
151 }
152
157# if __cplusplus >= 201402L
158 auto response = std::make_unique<HttpResponse>();
159# else
160 auto response = std::unique_ptr<HttpResponse>(new HttpResponse());
161# endif
162 response->ready = true;
163 response->status_code = 0;
164 response->error_code = submit_result.error_code;
165 response->error_message = submit_result.error_code.message();
166 return response;
167 }
168
172 inline void safe_set_response(
173 std::shared_ptr<std::promise<HttpResponsePtr>> promise,
174 HttpResponsePtr response) {
175 if (!response || !response->ready) return;
176 try {
177 promise->set_value(std::move(response));
178 } catch (const std::future_error& e) {
179 if (e.code() == std::make_error_condition(std::future_errc::promise_already_satisfied)) {
180 KURLYK_HANDLE_ERROR(e, "Promise already satisfied in HttpClient::request callback");
181 } else {
182 KURLYK_HANDLE_ERROR(e, "Future error in HttpClient::request callback");
183 }
184 } catch (const std::exception& e) {
185 KURLYK_HANDLE_ERROR(e, "Unhandled exception in HttpClient::request callback");
186 } catch (...) {
187 // Unknown fatal error in request callback
188 }
189 }
190
196 std::unique_ptr<HttpRequest> request_ptr,
197 HttpResponseCallback callback) {
199 std::move(request_ptr), std::move(callback));
200 if (submit_result) {
202 }
203 return submit_result;
204 }
205
210 inline bool http_request(
211 std::unique_ptr<HttpRequest> request_ptr,
212 HttpResponseCallback callback) {
213 return submit_http_request(std::move(request_ptr), std::move(callback)).accepted;
214 }
215
219 inline std::future<HttpResponsePtr> http_request(
220 std::unique_ptr<HttpRequest> request_ptr) {
221
222 auto promise = std::make_shared<std::promise<HttpResponsePtr>>();
223 auto future = promise->get_future();
224
225 HttpResponseCallback callback = [promise](HttpResponsePtr response) {
226 safe_set_response(promise, std::move(response));
227 };
228
229 const SubmitResult submit_result = submit_http_request(std::move(request_ptr), std::move(callback));
230 if (!submit_result) {
231 safe_set_response(promise, make_submit_error_response(submit_result));
232 }
233
234 return future;
235 }
236
245 inline uint64_t http_request(
246 const std::string &method,
247 const std::string &url,
248 const QueryParams &query,
249 const Headers &headers,
250 const std::string &content,
251 HttpResponseCallback callback) {
252# if __cplusplus >= 201402L
253 auto request_ptr = std::make_unique<HttpRequest>();
254# else
255 auto request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest());
256# endif
257
258 const uint64_t request_id = HttpRequestManager::get_instance().generate_request_id();
259 request_ptr->request_id = request_id;
260 request_ptr->set_url(url, query);
261 request_ptr->method = method;
262 request_ptr->headers = headers;
263 request_ptr->content = content;
264 if (http_request(std::move(request_ptr), std::move(callback))) return request_id;
265 return 0;
266 }
267
277 inline uint64_t http_request(
278 const std::string &method,
279 const std::string &url,
280 const QueryParams &query,
281 const Headers &headers,
282 const std::string &content,
283 bool streaming,
284 HttpResponseCallback callback) {
285# if __cplusplus >= 201402L
286 auto request_ptr = std::make_unique<HttpRequest>();
287# else
288 auto request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest());
289# endif
290
291 const uint64_t request_id = HttpRequestManager::get_instance().generate_request_id();
292 request_ptr->request_id = request_id;
293 request_ptr->set_url(url, query);
294 request_ptr->method = method;
295 request_ptr->headers = headers;
296 request_ptr->content = content;
297 request_ptr->streaming = streaming;
298 if (http_request(std::move(request_ptr), std::move(callback))) return request_id;
299 return 0;
300 }
301
309 inline std::pair<uint64_t, std::future<HttpResponsePtr>> http_request(
310 const std::string &method,
311 const std::string &url,
312 const QueryParams &query,
313 const Headers &headers,
314 const std::string &content) {
315
316# if __cplusplus >= 201402L
317 auto request_ptr = std::make_unique<HttpRequest>();
318# else
319 auto request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest());
320# endif
321
322 const uint64_t request_id = HttpRequestManager::get_instance().generate_request_id();
323 request_ptr->request_id = request_id;
324 request_ptr->set_url(url, query);
325 request_ptr->method = method;
326 request_ptr->headers = headers;
327 request_ptr->content = content;
328
329 auto promise = std::make_shared<std::promise<HttpResponsePtr>>();
330 auto future = promise->get_future();
331
332 HttpResponseCallback callback = [promise](HttpResponsePtr response) {
333 safe_set_response(promise, std::move(response));
334 };
335
336 const SubmitResult submit_result = submit_http_request(std::move(request_ptr), std::move(callback));
337 if (!submit_result) {
338 safe_set_response(promise, make_submit_error_response(submit_result));
339 }
340
341 return {request_id, std::move(future)};
342 }
343
353 inline uint64_t http_request(
354 const std::string &method,
355 const std::string &host,
356 const std::string &path,
357 const QueryParams &query,
358 const Headers &headers,
359 const std::string &content,
360 HttpResponseCallback callback) {
361
362# if __cplusplus >= 201402L
363 auto request_ptr = std::make_unique<HttpRequest>();
364# else
365 auto request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest());
366# endif
367
368 const uint64_t request_id = HttpRequestManager::get_instance().generate_request_id();
369 request_ptr->request_id = request_id;
370 request_ptr->set_url(host, path, query);
371 request_ptr->method = method;
372 request_ptr->headers = headers;
373 request_ptr->content = content;
374 if (http_request(std::move(request_ptr), std::move(callback))) return request_id;
375 return 0;
376 }
377
388 inline uint64_t http_request(
389 const std::string &method,
390 const std::string &host,
391 const std::string &path,
392 const QueryParams &query,
393 const Headers &headers,
394 const std::string &content,
395 bool streaming,
396 HttpResponseCallback callback) {
397
398# if __cplusplus >= 201402L
399 auto request_ptr = std::make_unique<HttpRequest>();
400# else
401 auto request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest());
402# endif
403
404 const uint64_t request_id = HttpRequestManager::get_instance().generate_request_id();
405 request_ptr->request_id = request_id;
406 request_ptr->set_url(host, path, query);
407 request_ptr->method = method;
408 request_ptr->headers = headers;
409 request_ptr->content = content;
410 request_ptr->streaming = streaming;
411 if (http_request(std::move(request_ptr), std::move(callback))) return request_id;
412 return 0;
413 }
414
421 inline uint64_t http_get(
422 const std::string &url,
423 const QueryParams& query,
424 const Headers& headers,
425 HttpResponseCallback callback) {
426 return http_request("GET", url, query, headers, std::string(), std::move(callback));
427 }
428
436 inline uint64_t http_get(
437 const std::string &url,
438 const QueryParams& query,
439 const Headers& headers,
440 bool streaming,
441 HttpResponseCallback callback) {
442 return http_request("GET", url, query, headers, std::string(), streaming, std::move(callback));
443 }
444
450 inline std::pair<uint64_t, std::future<HttpResponsePtr>> http_get(
451 const std::string& url,
452 const QueryParams& query,
453 const Headers& headers) {
454
455# if __cplusplus >= 201402L
456 auto request_ptr = std::make_unique<HttpRequest>();
457# else
458 auto request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest());
459# endif
460
461 const uint64_t request_id = HttpRequestManager::get_instance().generate_request_id();
462 request_ptr->request_id = request_id;
463 request_ptr->set_url(url, query);
464 request_ptr->method = "GET";
465 request_ptr->headers = headers;
466
467 auto promise = std::make_shared<std::promise<HttpResponsePtr>>();
468 auto future = promise->get_future();
469
470 HttpResponseCallback callback = [promise](HttpResponsePtr response) {
471 safe_set_response(promise, std::move(response));
472 };
473
474 const SubmitResult submit_result = submit_http_request(std::move(request_ptr), std::move(callback));
475 if (!submit_result) {
476 safe_set_response(promise, make_submit_error_response(submit_result));
477 }
478
479 return {request_id, std::move(future)};
480 }
481
489 inline uint64_t http_post(
490 const std::string &url,
491 const QueryParams& query,
492 const Headers& headers,
493 const std::string& content,
494 HttpResponseCallback callback) {
495 return http_request("POST", url, query, headers, content, std::move(callback));
496 }
497
506 inline uint64_t http_post(
507 const std::string &url,
508 const QueryParams& query,
509 const Headers& headers,
510 const std::string& content,
511 bool streaming,
512 HttpResponseCallback callback) {
513 return http_request("POST", url, query, headers, content, streaming, std::move(callback));
514 }
515
522 inline std::pair<uint64_t, std::future<HttpResponsePtr>> http_post(
523 const std::string& url,
524 const QueryParams& query,
525 const Headers& headers,
526 const std::string& content) {
527
528# if __cplusplus >= 201402L
529 auto request_ptr = std::make_unique<HttpRequest>();
530# else
531 auto request_ptr = std::unique_ptr<HttpRequest>(new HttpRequest());
532# endif
533
534 const uint64_t request_id = HttpRequestManager::get_instance().generate_request_id();
535 request_ptr->request_id = request_id;
536 request_ptr->set_url(url, query);
537 request_ptr->method = "POST";
538 request_ptr->headers = headers;
539 request_ptr->content = content;
540
541 auto promise = std::make_shared<std::promise<HttpResponsePtr>>();
542 auto future = promise->get_future();
543
544 HttpResponseCallback callback = [promise](HttpResponsePtr response) {
545 safe_set_response(promise, std::move(response));
546 };
547
548 const SubmitResult submit_result = submit_http_request(std::move(request_ptr), std::move(callback));
549 if (!submit_result) {
550 safe_set_response(promise, make_submit_error_response(submit_result));
551 }
552
553 return {request_id, std::move(future)};
554 }
555
556} // namespace kurlyk
557
558#endif // _KURLYK_HTTP_UTILS_HPP_INCLUDED
#define KURLYK_HANDLE_ERROR(e, msg)
std::size_t max_pending_requests() const
Returns the current maximum pending request count.
uint64_t generate_group_id()
Generates a new group ID.
void set_max_pending_requests(std::size_t max_pending_requests)
Sets the maximum number of pending requests accepted into the global queue.
void cancel_request_by_id(uint64_t request_id, std::function< void()> callback)
Cancels one request by request ID.
static HttpRequestManager & get_instance()
Get the singleton instance of HttpRequestManager.
HttpRateLimitHandlePtr get_rate_limit(long limit_id)
Returns a handle for a registered rate limit ID.
SubmitResult submit_request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Attempts to enqueue a new HTTP request and reports the admission result.
bool remove_limit(long limit_id)
Removes an existing rate limit with the specified identifier.
void cancel_requests_by_group_id(uint64_t group_id, std::function< void()> callback)
Cancels all requests with the specified group ID.
uint64_t generate_request_id()
Generates a new unique request ID.
HttpRateLimitHandlePtr create_rate_limit(long requests_per_period, long period_ms, bool sequential=false)
Creates a rate-limit handle with specified parameters.
Represents an HTTP request configuration.
Represents an HTTP response.
void notify()
Notifies the worker to begin processing requests or tasks.
static NetworkWorker & get_instance()
Get the singleton instance of NetworkWorker.
Primary namespace for the Kurlyk library, encompassing initialization, request management,...
HttpRateLimitHandlePtr create_rate_limit(long requests_per_period, long period_ms, bool sequential=false)
Creates a RAII rate-limit handle with specified parameters.
Definition utils.hpp:18
std::size_t max_pending_requests()
Returns the current global pending queue limit.
Definition utils.hpp:83
std::function< void(HttpResponsePtr response)> HttpResponseCallback
Callback invoked with an HTTP response.
void set_max_pending_requests(std::size_t max_pending_requests)
Sets the maximum number of requests accepted into the global pending queue.
Definition utils.hpp:77
void safe_set_response(std::shared_ptr< std::promise< HttpResponsePtr > > promise, HttpResponsePtr response)
Safely sets an HTTP response on the provided promise.
Definition utils.hpp:172
std::unique_ptr< HttpResponse > HttpResponsePtr
Owning pointer to an HTTP response.
bool http_request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Sends an HTTP request with callback.
Definition utils.hpp:210
HttpRateLimitHandlePtr get_rate_limit(long limit_id)
Returns a manager-owned rate-limit handle by ID.
Definition utils.hpp:44
void cancel_requests_by_group_id(uint64_t group_id, std::function< void()> callback)
Cancels all requests with the specified group ID.
Definition utils.hpp:123
utils::CaseInsensitiveMultimap Headers
Alias for HTTP headers, providing a case-insensitive unordered multimap.
uint64_t generate_request_id()
Generates a new unique request ID.
Definition utils.hpp:65
uint64_t generate_group_id()
Generates a new group ID.
Definition utils.hpp:71
uint64_t http_get(const std::string &url, const QueryParams &query, const Headers &headers, HttpResponseCallback callback)
Sends an asynchronous HTTP GET request with a callback.
Definition utils.hpp:421
bool remove_limit(long limit_id)
Releases manager-owned rate-limit handle by ID.
Definition utils.hpp:52
SubmitResult submit_http_request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Attempts to submit an HTTP request and reports the admission result.
Definition utils.hpp:195
HttpRateLimitHandlePtr create_rate_limit_rps(long requests_per_second, bool sequential=false)
Creates a RAII rate-limit based on Requests Per Second (RPS).
Definition utils.hpp:37
std::shared_ptr< HttpRateLimitHandle > HttpRateLimitHandlePtr
Shared RAII handle for HTTP rate limits.
HttpRateLimitHandlePtr create_rate_limit_rpm(long requests_per_minute, bool sequential=false)
Creates a RAII rate-limit based on Requests Per Minute (RPM).
Definition utils.hpp:27
utils::CaseInsensitiveMultimap QueryParams
Alias for query parameters in HTTP requests, stored case-insensitively.
void cancel_request_by_id(uint64_t request_id, std::function< void()> callback)
Cancels a request by its unique identifier.
Definition utils.hpp:90
uint64_t http_post(const std::string &url, const QueryParams &query, const Headers &headers, const std::string &content, HttpResponseCallback callback)
Sends an asynchronous HTTP POST request with a callback.
Definition utils.hpp:489
HttpResponsePtr make_submit_error_response(const SubmitResult &submit_result)
Creates a ready HTTP response describing a synchronous submission rejection.
Definition utils.hpp:156
Represents the synchronous result of trying to enqueue or submit work.
bool accepted
Indicates whether the work item was accepted for processing.
std::error_code error_code
Describes the rejection reason when accepted is false.