2#ifndef KURLYK_HEADER_KURLYK_HTTP_HTTP_CLIENT_HPP_INCLUDED
3#define KURLYK_HEADER_KURLYK_HTTP_HTTP_CLIENT_HPP_INCLUDED
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) {
111 if (worker.is_worker_thread()) {
114 uint64_t waiter_id = 0;
117 if (future.wait_for(timeout) == std::future_status::timeout) {
125 }
catch (
const std::exception& e) {
194#if KURLYK_AUTH_SUPPORT
202 void set_auth_provider(std::shared_ptr<http::auth::IAuthProvider> provider) {
203 m_auth_provider = provider;
207 void clear_auth_provider() {
208 m_auth_provider.reset();
212 bool has_auth_provider()
const {
213 return m_auth_provider !=
nullptr;
217 std::shared_ptr<http::auth::IAuthProvider> auth_provider()
const {
218 return m_auth_provider;
288 long requests_per_period,
291 bool sequential =
false) {
299 instance.create_rate_limit(requests_per_period, period_ms, sequential);
305 instance.create_rate_limit(requests_per_period, period_ms, sequential);
317 long requests_per_minute,
319 bool sequential =
false) {
320 long period_ms = 60000;
330 long requests_per_second,
332 bool sequential =
false) {
333 long period_ms = 1000;
363 const std::string& general_key,
364 const std::string& specific_key) {
375 bool identity =
false,
376 bool deflate =
false,
378 bool brotli =
false) {
455 const std::string& ip,
468 const std::string& ip,
470 const std::string& username,
471 const std::string& password,
480 const std::string& username,
481 const std::string& password) {
588 std::unique_ptr<HttpRequest> request_ptr,
600 std::move(request_ptr), std::move(callback));
606 return submit_result;
618 const std::string &method,
619 const std::string& path,
622 const std::string &content,
638 const std::string &method,
639 const std::string& path,
642 const std::string &content,
643 long specific_rate_limit_id,
652 std::move(callback));
665 const std::string &method,
666 const std::string& path,
669 const std::string &content,
672 auto request_ptr =
make_request(method, path, query, headers, content);
673 request_ptr->specific_rate_limit = specific_rate_limit;
674 return request(std::move(request_ptr), std::move(callback));
684 const std::string& path,
688 return request(
"GET", path, query, headers, std::string(), std::move(callback));
699 const std::string& path,
702 const std::string& content,
704 return request(
"POST", path, query, headers, content, std::move(callback));
716 const std::string& path,
719 long specific_rate_limit_id,
721 return request(
"GET", path, query, headers, std::string(), specific_rate_limit_id, std::move(callback));
732 const std::string& path,
737 return request(
"GET", path, query, headers, std::string(), specific_rate_limit, std::move(callback));
750 const std::string& path,
753 const std::string& content,
754 long specific_rate_limit_id,
756 return request(
"POST", path, query, headers, content, specific_rate_limit_id, std::move(callback));
768 const std::string& path,
771 const std::string& content,
774 return request(
"POST", path, query, headers, content, specific_rate_limit, std::move(callback));
785 const std::string& method,
786 const std::string& path,
789 const std::string& content) {
803 const std::string& method,
804 const std::string& path,
807 const std::string& content,
808 long specific_rate_limit_id) {
827 const std::string& method,
828 const std::string& path,
831 const std::string& content,
833 auto request_ptr =
make_request(method, path, query, headers, content);
834 request_ptr->specific_rate_limit = specific_rate_limit;
843 std::future<HttpResponsePtr>
get(
844 const std::string& path,
847 return request(
"GET", path, query, headers, std::string());
856 std::future<HttpResponsePtr>
post(
857 const std::string& path,
860 const std::string& content) {
861 return request(
"POST", path, query, headers, content);
871 std::future<HttpResponsePtr>
get(
872 const std::string& path,
875 long specific_rate_limit_id) {
876 return request(
"GET", path, query, headers, std::string(), specific_rate_limit_id);
887 std::future<HttpResponsePtr>
post(
888 const std::string& path,
891 const std::string& content,
892 long specific_rate_limit_id) {
893 return request(
"POST", path, query, headers, content, specific_rate_limit_id);
902 std::future<HttpResponsePtr>
get(
903 const std::string& path,
907 return request(
"GET", path, query, headers, std::string(), specific_rate_limit);
917 std::future<HttpResponsePtr>
post(
918 const std::string& path,
921 const std::string& content,
923 return request(
"POST", path, query, headers, content, specific_rate_limit);
933# if KURLYK_AUTH_SUPPORT
934 std::shared_ptr<http::auth::IAuthProvider> m_auth_provider;
942 std::unique_ptr<HttpRequest> request_ptr,
947 void set_header(
const std::string& name,
const std::string& value) {
953 const std::string& method,
954 const std::string& path,
957 const std::string& content)
const {
958# if __cplusplus >= 201402L
959 auto request_ptr = std::make_unique<HttpRequest>(
m_request);
965 request_ptr->method = method;
966 request_ptr->set_url(
m_host, path, query);
967 request_ptr->headers.insert(headers.begin(), headers.end());
968 request_ptr->content = content;
969# if KURLYK_AUTH_SUPPORT
970 if (m_auth_provider) {
971 m_auth_provider->authorize(*request_ptr);
978 auto promise = std::make_shared<std::promise<HttpResponsePtr>>();
979 auto future = promise->get_future();
992 auto promise = std::make_shared<std::promise<void>>();
993 auto future = promise->get_future();
995 const uint64_t registered_waiter_id =
1000 promise->set_value();
1001 } catch (
const std::future_error& e) {
1002 if (e.code() == std::make_error_condition(std::future_errc::promise_already_satisfied)) {
1003 KURLYK_HANDLE_ERROR(e,
"Promise already satisfied in HttpClient::wait_requests callback");
1007 }
catch (
const std::exception& e) {
1014 *waiter_id = registered_waiter_id;
1024 std::shared_ptr<std::promise<HttpResponsePtr>> promise,
1026 if (!response || !response->ready)
return;
1028 promise->set_value(std::move(response));
1029 }
catch (
const std::future_error& e) {
1030 if (e.code() == std::make_error_condition(std::future_errc::promise_already_satisfied)) {
1035 }
catch (
const std::exception& e) {
1046# if __cplusplus >= 201402L
1047 auto response = std::make_unique<HttpResponse>();
1049 auto response = std::unique_ptr<HttpResponse>(
new HttpResponse());
1051 response->ready =
true;
1052 response->status_code = 0;
1053 response->error_code = submit_result.
error_code;
1054 response->error_message = submit_result.
error_code.message();
1063 std::shared_ptr<std::promise<HttpResponsePtr>> promise,
1064 std::unique_ptr<HttpRequest> request_ptr,
1068 if (!submit_result) {
1071 }
catch (
const std::exception& e) {
1074 promise->set_exception(std::current_exception());
1079 promise->set_exception(std::current_exception());
1086 static std::once_flag once;
1087 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 the number of admitted requests whose final callback is still pending for this 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.
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.
std::future< void > make_wait_requests_future(uint64_t *waiter_id)
Creates a future that becomes ready when all requests in this client group finish.
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 admitted requests that have not delivered their final callback for a group.
static HttpRequestManager & get_instance()
Get the singleton instance of HttpRequestManager.
uint64_t 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.
bool cancel_wait_requests_by_group_id(uint64_t group_id, uint64_t waiter_id)
Removes a previously registered group waiter.
uint64_t generate_request_id()
Generates a new unique request ID.
Represents an HTTP request configuration.
bool proxy_tunnel
Enable proxy tunneling.
void set_proxy_type(ProxyType type)
Sets the proxy type.
bool head_only
If true, does not download the response body (HEAD-like behavior).
void set_cert_file(const std::string &cert_file)
Sets the client certificate file path.
void set_proxy_auth(const std::string &auth)
Sets the proxy authentication credentials.
bool follow_location
Automatically follow HTTP redirects.
bool debug_header
Include headers in debug output (CURLOPT_HEADER).
bool verbose
Enable verbose output (CURLOPT_VERBOSE).
void set_retry_attempts(long retry_attempts, long retry_delay_ms)
Sets the number of retry attempts and delay before retrying.
void set_proxy_server(const std::string &server)
Sets the proxy server address.
void set_ca_file(const std::string &ca_file)
Sets the path to the CA certificate file.
void set_timeout(long timeout)
Sets the request timeout.
void set_valid_statuses(const std::set< long > &statuses)
Sets the valid HTTP status codes, replacing any existing values.
bool streaming
Enable intermediate callbacks for response body chunks.
void set_cookie(const std::string &cookie)
Sets the cookie data.
Headers headers
HTTP request headers.
void set_connect_timeout(long connect_timeout)
Sets the connection timeout.
void set_proxy(const std::string &ip, int port)
Sets the proxy server address.
bool auto_referer
Automatically set Referer header.
void clear_valid_statuses()
Clears all valid status codes.
std::string general_rate_limit_key
Key used to separate general rate limit state; empty means default shared state.
std::string specific_rate_limit_key
Key used to separate specific rate limit state; empty means default shared state.
void set_accept_encoding(bool identity=false, bool deflate=false, bool gzip=false, bool brotli=false)
Sets the Accept-Encoding header with optional encoding types.
std::string accept_encoding
Accept-Encoding header.
long max_redirects
Maximum allowed redirects.
void set_user_agent(const std::string &user_agent)
Sets the User-Agent header.
HttpRateLimitHandlePtr general_rate_limit
General rate limit handle.
uint64_t group_id
ID shared by related requests, for example all requests created by one HttpClient.
HttpRateLimitHandlePtr specific_rate_limit
Specific rate limit handle.
void add_valid_status(long status)
Adds a single valid HTTP status code.
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.
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.
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.