2#ifndef _KURLYK_HTTP_CLIENT_HPP_INCLUDED
3#define _KURLYK_HTTP_CLIENT_HPP_INCLUDED
55 const uint64_t group_id =
m_request.group_id;
56 if (worker.is_worker_thread()) {
58 manager.cancel_requests_by_group_id(group_id,
nullptr);
62 auto promise = std::make_shared<std::promise<void>>();
63 auto future = promise->get_future();
64 manager.cancel_requests_by_group_id(group_id, [promise](){
67 }
catch (
const std::future_error& e) {
68 if (e.code() == std::make_error_condition(std::future_errc::promise_already_satisfied)) {
73 }
catch (
const std::exception& e) {
82 }
catch (
const std::exception& e) {
93 if (worker.is_worker_thread()) {
94 throw std::logic_error(
"HttpClient::wait_requests() must not be called from the network worker thread");
100 }
catch (
const std::exception& e) {
113 if (worker.is_worker_thread()) {
118 if (future.wait_for(timeout) == std::future_status::timeout) {
123 }
catch (
const std::exception& e) {
164 instance.remove_limit(
m_request.general_rate_limit);
172 instance.remove_limit(
m_request.specific_rate_limit);
192#if KURLYK_AUTH_SUPPORT
200 void set_auth_provider(std::shared_ptr<http::auth::IAuthProvider> provider) {
201 m_auth_provider = provider;
205 void clear_auth_provider() {
206 m_auth_provider.reset();
210 bool has_auth_provider()
const {
211 return m_auth_provider !=
nullptr;
215 std::shared_ptr<http::auth::IAuthProvider> auth_provider()
const {
216 return m_auth_provider;
286 long requests_per_period,
289 bool sequential =
false) {
297 instance.create_rate_limit(requests_per_period, period_ms, sequential);
303 instance.create_rate_limit(requests_per_period, period_ms, sequential);
315 long requests_per_minute,
317 bool sequential =
false) {
318 long period_ms = 60000;
328 long requests_per_second,
330 bool sequential =
false) {
331 long period_ms = 1000;
361 const std::string& general_key,
362 const std::string& specific_key) {
363 m_request.general_rate_limit_key = general_key;
364 m_request.specific_rate_limit_key = specific_key;
373 bool identity =
false,
374 bool deflate =
false,
376 bool brotli =
false) {
377 m_request.set_accept_encoding(identity, deflate, gzip, brotli);
414 if (value)
m_request.headers.emplace(
"dnt",
"1");
453 const std::string& ip,
466 const std::string& ip,
468 const std::string& username,
469 const std::string& password,
471 m_request.set_proxy(ip, port, username, password, type);
478 const std::string& username,
479 const std::string& password) {
480 m_request.set_proxy_auth(username, password);
505 m_request.set_retry_attempts(retry_attempts, retry_delay_ms);
558 m_request.set_connect_timeout(connect_timeout);
586 std::unique_ptr<HttpRequest> request_ptr,
598 std::move(request_ptr), std::move(callback));
604 return submit_result;
616 const std::string &method,
617 const std::string& path,
620 const std::string &content,
636 const std::string &method,
637 const std::string& path,
640 const std::string &content,
641 long specific_rate_limit_id,
650 std::move(callback));
663 const std::string &method,
664 const std::string& path,
667 const std::string &content,
670 auto request_ptr =
make_request(method, path, query, headers, content);
671 request_ptr->specific_rate_limit = specific_rate_limit;
672 return request(std::move(request_ptr), std::move(callback));
682 const std::string& path,
686 return request(
"GET", path, query, headers, std::string(), std::move(callback));
697 const std::string& path,
700 const std::string& content,
702 return request(
"POST", path, query, headers, content, std::move(callback));
714 const std::string& path,
717 long specific_rate_limit_id,
719 return request(
"GET", path, query, headers, std::string(), specific_rate_limit_id, std::move(callback));
730 const std::string& path,
735 return request(
"GET", path, query, headers, std::string(), specific_rate_limit, std::move(callback));
748 const std::string& path,
751 const std::string& content,
752 long specific_rate_limit_id,
754 return request(
"POST", path, query, headers, content, specific_rate_limit_id, std::move(callback));
766 const std::string& path,
769 const std::string& content,
772 return request(
"POST", path, query, headers, content, specific_rate_limit, std::move(callback));
783 const std::string& method,
784 const std::string& path,
787 const std::string& content) {
801 const std::string& method,
802 const std::string& path,
805 const std::string& content,
806 long specific_rate_limit_id) {
825 const std::string& method,
826 const std::string& path,
829 const std::string& content,
831 auto request_ptr =
make_request(method, path, query, headers, content);
832 request_ptr->specific_rate_limit = specific_rate_limit;
841 std::future<HttpResponsePtr>
get(
842 const std::string& path,
845 return request(
"GET", path, query, headers, std::string());
854 std::future<HttpResponsePtr>
post(
855 const std::string& path,
858 const std::string& content) {
859 return request(
"POST", path, query, headers, content);
869 std::future<HttpResponsePtr>
get(
870 const std::string& path,
873 long specific_rate_limit_id) {
874 return request(
"GET", path, query, headers, std::string(), specific_rate_limit_id);
885 std::future<HttpResponsePtr>
post(
886 const std::string& path,
889 const std::string& content,
890 long specific_rate_limit_id) {
891 return request(
"POST", path, query, headers, content, specific_rate_limit_id);
900 std::future<HttpResponsePtr>
get(
901 const std::string& path,
905 return request(
"GET", path, query, headers, std::string(), specific_rate_limit);
915 std::future<HttpResponsePtr>
post(
916 const std::string& path,
919 const std::string& content,
921 return request(
"POST", path, query, headers, content, specific_rate_limit);
931# if KURLYK_AUTH_SUPPORT
932 std::shared_ptr<http::auth::IAuthProvider> m_auth_provider;
940 std::unique_ptr<HttpRequest> request_ptr,
945 void set_header(
const std::string& name,
const std::string& value) {
951 const std::string& method,
952 const std::string& path,
955 const std::string& content)
const {
956# if __cplusplus >= 201402L
957 auto request_ptr = std::make_unique<HttpRequest>(
m_request);
963 request_ptr->method = method;
964 request_ptr->set_url(
m_host, path, query);
965 request_ptr->headers.insert(headers.begin(), headers.end());
966 request_ptr->content = content;
967# if KURLYK_AUTH_SUPPORT
968 if (m_auth_provider) {
969 m_auth_provider->authorize(*request_ptr);
976 auto promise = std::make_shared<std::promise<HttpResponsePtr>>();
977 auto future = promise->get_future();
990 auto promise = std::make_shared<std::promise<void>>();
991 auto future = promise->get_future();
997 promise->set_value();
998 } catch (
const std::future_error& e) {
999 if (e.code() == std::make_error_condition(std::future_errc::promise_already_satisfied)) {
1000 KURLYK_HANDLE_ERROR(e,
"Promise already satisfied in HttpClient::wait_requests callback");
1004 }
catch (
const std::exception& e) {
1018 std::shared_ptr<std::promise<HttpResponsePtr>> promise,
1020 if (!response || !response->ready)
return;
1022 promise->set_value(std::move(response));
1023 }
catch (
const std::future_error& e) {
1024 if (e.code() == std::make_error_condition(std::future_errc::promise_already_satisfied)) {
1029 }
catch (
const std::exception& e) {
1040# if __cplusplus >= 201402L
1041 auto response = std::make_unique<HttpResponse>();
1043 auto response = std::unique_ptr<HttpResponse>(
new HttpResponse());
1045 response->ready =
true;
1046 response->status_code = 0;
1047 response->error_code = submit_result.
error_code;
1048 response->error_message = submit_result.
error_code.message();
1057 std::shared_ptr<std::promise<HttpResponsePtr>> promise,
1058 std::unique_ptr<HttpRequest> request_ptr,
1062 if (!submit_result) {
1065 }
catch (
const std::exception& e) {
1068 promise->set_exception(std::current_exception());
1073 promise->set_exception(std::current_exception());
1080 static std::once_flag once;
1081 std::call_once(once, []() {
Defines the IAuthProvider interface for HTTP authentication strategies.
#define KURLYK_HANDLE_ERROR(e, msg)
bool get(const std::string &path, const QueryParams &query, const Headers &headers, long specific_rate_limit_id, HttpResponseCallback callback)
Sends a GET request with a temporary specific rate limit found by ID.
bool request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Adds the request to the request manager and notifies the worker to process it.
void set_proxy_auth(const std::string &auth)
Sets the proxy authentication credentials.
std::unique_ptr< HttpRequest > make_request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content) const
bool m_owns_general_rate_limit
Flag indicating if the client owns the general rate limit.
~HttpClient()
Destroys the client, cancels requests associated with this client, and releases owned rate limits.
void wait_requests()
Waits until all requests associated with this client group finish.
void set_rate_limit(long requests_per_period, long period_ms, RateLimitType type=RateLimitType::RL_GENERAL, bool sequential=false)
Creates and assigns an owned rate limit for future requests.
HttpRequest m_request
Request defaults shared by requests created by this client.
bool wait_requests_for(std::chrono::milliseconds timeout)
Waits until all requests associated with this client group finish or timeout expires.
std::size_t max_in_flight() const
Returns this client's configured admission cap.
void set_valid_statuses(const std::set< long > &statuses)
Replaces all valid HTTP status codes for the request.
void set_head_only(bool value)
Configures whether to send only the HTTP headers (HEAD request).
void set_verbose(bool verbose)
Enables or disables verbose output.
void set_accept_language(const std::string &value)
Sets the Accept-Language header value.
std::future< HttpResponsePtr > request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, long specific_rate_limit_id)
Sends an HTTP request with a temporary specific rate limit found by ID and returns a future with the ...
std::string m_host
The base host URL for the HTTP client.
void set_max_redirects(long max_redirects)
Sets the maximum number of redirects for the client.
std::future< HttpResponsePtr > post(const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, long specific_rate_limit_id)
Sends an asynchronous POST request with a temporary specific rate limit found by ID.
void set_content_type(const std::string &value)
Sets the Content-Type header value.
bool post(const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, HttpResponseCallback callback)
Sends a POST request.
bool request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, HttpResponseCallback callback)
Sends an HTTP request with the specified method, path, and parameters.
HttpClient(const HttpClient &)=delete
void add_valid_status(long status)
Adds a valid HTTP status code to the request.
std::future< HttpResponsePtr > get(const std::string &path, const QueryParams &query, const Headers &headers, const HttpRateLimitHandlePtr &specific_rate_limit)
Sends an asynchronous GET request with a temporary specific rate limit.
std::future< HttpResponsePtr > request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, const HttpRateLimitHandlePtr &specific_rate_limit)
Sends an HTTP request with a temporary specific rate limit and returns a future with the response.
HttpClient()
Default constructor for HttpClient.
void set_streaming(bool streaming)
Enables or disables intermediate callbacks for response body chunks.
void set_ca_file(const std::string &ca_file)
Sets the path to the CA certificate file.
void clear_valid_statuses()
Clears the set of valid HTTP status codes for the request.
SubmitResult submit_request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Attempts to submit a prepared request to the global HTTP manager.
std::future< HttpResponsePtr > post(const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, const HttpRateLimitHandlePtr &specific_rate_limit)
Sends an asynchronous POST request with a temporary specific rate limit.
std::future< HttpResponsePtr > request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content)
Sends an HTTP request with a specified method, path, and parameters, and returns a future with the re...
void set_proxy(const std::string &ip, int port, ProxyType type=ProxyType::PROXY_HTTP)
Sets the proxy server address.
bool set_rate_limit_handle(const HttpRateLimitHandlePtr &limit, RateLimitType type=RateLimitType::RL_GENERAL)
Sets an existing rate-limit handle for future requests.
void safe_submit_request(std::shared_ptr< std::promise< HttpResponsePtr > > promise, std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Submits a request and propagates any failure to the provided promise.
bool get(const std::string &path, const QueryParams &query, const Headers &headers, const HttpRateLimitHandlePtr &specific_rate_limit, HttpResponseCallback callback)
Sends a GET request with a temporary specific rate limit.
void set_cert_file(const std::string &cert_file)
Sets the client certificate file path.
static void safe_set_response(std::shared_ptr< std::promise< HttpResponsePtr > > promise, HttpResponsePtr response)
Safely sets the response value on the given promise.
void set_auto_referer(bool value)
Configures whether to automatically set the Referer header on redirects.
void set_connect_timeout(long connect_timeout)
Sets the connection timeout duration.
void set_retry_attempts(long retry_attempts, long retry_delay_ms)
Sets retry attempts and delay between retries for HTTP requests.
void set_rate_limit_rps(long requests_per_second, RateLimitType type=RateLimitType::RL_GENERAL, bool sequential=false)
Sets the rate limit based on requests per second (RPS).
void set_timeout(long timeout)
Sets the timeout duration for HTTP requests.
void set_proxy_server(const std::string &server)
Sets the proxy server address.
std::future< HttpResponsePtr > get(const std::string &path, const QueryParams &query, const Headers &headers)
Sends a GET request asynchronously and returns a future with the response.
void set_rate_limit_rpm(long requests_per_minute, RateLimitType type=RateLimitType::RL_GENERAL, bool sequential=false)
Sets the rate limit based on requests per minute (RPM).
void clear_rate_limit(RateLimitType type=RateLimitType::RL_GENERAL)
Clears the configured rate limit of the specified type.
void set_referer(const std::string &value)
Sets the Referer header value.
void set_follow_location(bool value)
Configures whether to follow redirects automatically.
void set_proxy(const std::string &ip, const int port, const std::string &username, const std::string &password, ProxyType type=ProxyType::PROXY_HTTP)
Sets the proxy server address with authentication details.
void set_specific_rate_limit_key(const std::string &key)
Sets the partition key for the specific rate limit.
bool assign_rate_limit_handle(const HttpRateLimitHandlePtr &limit, RateLimitType type=RateLimitType::RL_GENERAL)
Assigns an existing rate-limit handle to future requests.
void set_cookie(const std::string &cookie)
Sets the cookie string for HTTP requests.
std::future< HttpResponsePtr > get(const std::string &path, const QueryParams &query, const Headers &headers, long specific_rate_limit_id)
Sends an asynchronous GET request with a temporary specific rate limit found by ID.
std::future< HttpResponsePtr > post(const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content)
Sends a POST request asynchronously and returns a future with the response.
void set_accept_encoding(const std::string &value)
Sets a custom Accept-Encoding header value.
bool assign_rate_limit_id(long limit_id, RateLimitType type=RateLimitType::RL_GENERAL)
Assigns an existing rate limit to future requests by ID.
std::size_t in_flight_requests() const
Returns number of pending, active, and retry requests currently observed for this client group.
HttpClient(HttpClient &&)=delete
void set_general_rate_limit_key(const std::string &key)
Sets the partition key for the general rate limit.
void set_user_agent(const std::string &user_agent)
Sets the User-Agent header.
void set_origin(const std::string &value)
Sets the Origin header value.
bool request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, const HttpRateLimitHandlePtr &specific_rate_limit, HttpResponseCallback callback)
Sends an HTTP request with a temporary specific rate limit.
HttpClient(const std::string &host)
Constructs an HttpClient with the specified host.
std::future< void > make_wait_requests_future()
Creates a future that becomes ready when all requests in this client group finish.
void set_max_in_flight(std::size_t max_in_flight)
Sets maximum number of requests this client may submit while its group is busy.
void set_proxy_tunnel(bool value)
Configures whether to use a tunneling proxy for HTTP requests.
bool post(const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, long specific_rate_limit_id, HttpResponseCallback callback)
Sends a POST request with a temporary specific rate limit found by ID.
static HttpResponsePtr make_submit_error_response(const SubmitResult &submit_result)
Creates a ready HTTP response describing a synchronous submission rejection.
bool m_owns_specific_rate_limit
Flag indicating if the client owns the specific rate limit.
static void ensure_initialized()
Ensures that the network worker and request manager are initialized.
bool post(const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, const HttpRateLimitHandlePtr &specific_rate_limit, HttpResponseCallback callback)
Sends a POST request with a temporary specific rate limit.
HttpClient & operator=(HttpClient &&)=delete
void set_host(const std::string &host)
Sets the host URL for the HTTP client.
bool get(const std::string &path, const QueryParams &query, const Headers &headers, HttpResponseCallback callback)
Sends a GET request.
std::size_t m_max_in_flight
Maximum number of in-flight requests for this client group, or 0 for disabled.
void set_debug_header(bool debug_header)
Enables or disables debug headers.
void set_rate_limit_key(const std::string &key)
Sets the partition key for both rate limits (general and specific).
std::future< HttpResponsePtr > submit_future_request(std::unique_ptr< HttpRequest > request_ptr)
void set_proxy_auth(const std::string &username, const std::string &password)
Sets proxy authentication credentials.
void set_headers(const kurlyk::Headers &headers)
Sets the default headers for HTTP requests.
HttpClient & operator=(const HttpClient &)=delete
void set_rate_limit_keys(const std::string &general_key, const std::string &specific_key)
Sets independent partition keys for general and specific rate limits.
bool set_rate_limit_id(long limit_id, RateLimitType type=RateLimitType::RL_GENERAL)
Sets the rate limit ID for the HTTP request (alias for assign_rate_limit_id).
void set_dnt(const bool value)
Sets the Do Not Track (DNT) header value.
std::mutex m_submit_mutex
Protects client-side submission settings and admission checks.
bool request(const std::string &method, const std::string &path, const QueryParams &query, const Headers &headers, const std::string &content, long specific_rate_limit_id, HttpResponseCallback callback)
Sends an HTTP request with a temporary specific rate limit found by ID.
void set_header(const std::string &name, const std::string &value)
void set_accept_encoding(bool identity=false, bool deflate=false, bool gzip=false, bool brotli=false)
Sets the Accept-Encoding header.
void set_proxy_type(ProxyType type)
Sets the proxy type.
void cancel_requests()
Cancels requests associated with this client and waits for cancellation callbacks.
uint64_t generate_group_id()
Generates a new group ID.
std::size_t group_request_count(uint64_t group_id) const
Counts pending, failed, and active requests for a group.
static HttpRequestManager & get_instance()
Get the singleton instance of HttpRequestManager.
void wait_requests_by_group_id(uint64_t group_id, std::function< void()> callback)
Registers a callback invoked after all requests from a group finish.
SubmitResult submit_request(std::unique_ptr< HttpRequest > request_ptr, HttpResponseCallback callback)
Attempts to enqueue a new HTTP request and reports the admission result.
uint64_t generate_request_id()
Generates a new unique request ID.
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.
void start(const bool use_async)
Starts the worker thread for asynchronous task processing.
#define KURLYK_AUTO_INIT_USE_ASYNC
Determines whether the NetworkWorker runs in a background thread during automatic initialization.
@ QueueLimitExceeded
Operation was rejected because the bounded queue is already full.
std::error_code make_error_code(ClientError e)
Creates a std::error_code from a ClientError value.
Primary namespace for the Kurlyk library, encompassing initialization, request management,...
std::function< void(HttpResponsePtr response)> HttpResponseCallback
Callback invoked with an HTTP response.
RateLimitType
Defines rate limit scope categories.
@ RL_GENERAL
Applies globally to all requests.
@ RL_SPECIFIC
Applies to specific client/request.
void safe_set_response(std::shared_ptr< std::promise< HttpResponsePtr > > promise, HttpResponsePtr response)
Safely sets an HTTP response on the provided promise.
ProxyType
Enumeration of supported proxy types compatible with libcurl.
std::unique_ptr< HttpResponse > HttpResponsePtr
Owning pointer to an HTTP response.
HttpRateLimitHandlePtr get_rate_limit(long limit_id)
Returns a manager-owned rate-limit handle by ID.
utils::CaseInsensitiveMultimap Headers
Alias for HTTP headers, providing a case-insensitive unordered multimap.
std::shared_ptr< HttpRateLimitHandle > HttpRateLimitHandlePtr
Shared RAII handle for HTTP rate limits.
utils::CaseInsensitiveMultimap QueryParams
Alias for query parameters in HTTP requests, stored case-insensitively.
HttpResponsePtr make_submit_error_response(const SubmitResult &submit_result)
Creates a ready HTTP response describing a synchronous submission rejection.
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.