Skip to content
This repository was archived by the owner on Mar 24, 2026. It is now read-only.

Commit 46ada98

Browse files
Privacy Sandbox Teamcopybara-github
authored andcommitted
feat: Copy http_fetcher_async from B&A to common repo
This is part of a series of CLs to copy the KV BYOS clients from B&A to common repo. Bug: 411430242 Change-Id: Ie955fa3c7fb14a16a9b51d4f65a643d741c9b561 GitOrigin-RevId: 58d0430517544fa2de8e97a203965d13dd5e38dc
1 parent 1595c9d commit 46ada98

4 files changed

Lines changed: 347 additions & 0 deletions

File tree

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
load("@rules_cc//cc:defs.bzl", "cc_library")
16+
17+
cc_library(
18+
name = "http_fetcher_async",
19+
hdrs = [
20+
"http_fetcher_async.h",
21+
],
22+
visibility = ["//visibility:public"],
23+
deps = [
24+
":curl_request_data",
25+
"@com_google_absl//absl/time",
26+
],
27+
)
28+
29+
cc_library(
30+
name = "curl_request_data",
31+
srcs = [
32+
"curl_request_data.cc",
33+
],
34+
hdrs = [
35+
"curl_request_data.h",
36+
],
37+
deps = [
38+
"@com_google_absl//absl/container:flat_hash_map",
39+
"@com_google_absl//absl/functional:any_invocable",
40+
"@com_google_absl//absl/log:check",
41+
"@com_google_absl//absl/status",
42+
"@com_google_absl//absl/status:statusor",
43+
"@com_google_absl//absl/strings",
44+
"@com_google_absl//absl/time",
45+
"@curl",
46+
"@libevent//:event",
47+
],
48+
)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "src/clients/http_fetcher_async/curl_request_data.h"
16+
17+
#include <string>
18+
#include <utility>
19+
#include <vector>
20+
21+
namespace privacy_sandbox::server_common::clients {
22+
23+
// TODO(b/412330778): Refactor to factory function. `curl_easy_init` failures
24+
// (nullptr being returned) should be handled, and therefore can't be done in a
25+
// ctor (and especially not in an initializer list).
26+
// This should have no impact on existing B&A code, since CurlRequestData
27+
// is only used in this directory.
28+
CurlRequestData::CurlRequestData(const std::vector<std::string>& headers,
29+
OnDoneFetchUrlWithMetadata on_done,
30+
std::vector<std::string> response_header_keys,
31+
bool include_redirect_url)
32+
: req_handle(curl_easy_init()),
33+
done_callback(std::move(on_done)),
34+
response_headers(std::move(response_header_keys)),
35+
include_redirect_url(include_redirect_url) {
36+
for (const auto& header : headers) {
37+
headers_list_ptr = curl_slist_append(headers_list_ptr, header.c_str());
38+
}
39+
}
40+
41+
CurlRequestData::~CurlRequestData() {
42+
curl_slist_free_all(headers_list_ptr);
43+
curl_easy_cleanup(req_handle);
44+
}
45+
46+
} // namespace privacy_sandbox::server_common::clients
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef SRC_CLIENTS_HTTP_FETCHER_ASYNC_CURL_REQUEST_DATA_H_
16+
#define SRC_CLIENTS_HTTP_FETCHER_ASYNC_CURL_REQUEST_DATA_H_
17+
18+
#include <memory>
19+
#include <string>
20+
#include <vector>
21+
22+
#include <curl/curl.h>
23+
#include <event2/event.h>
24+
#include <event2/event_struct.h>
25+
26+
#include "absl/container/flat_hash_map.h"
27+
#include "absl/functional/any_invocable.h"
28+
#include "absl/status/statusor.h"
29+
#include "absl/time/time.h"
30+
31+
namespace privacy_sandbox::server_common::clients {
32+
33+
using OnDoneFetchUrl = absl::AnyInvocable<void(absl::StatusOr<std::string>) &&>;
34+
using OnDoneFetchUrls =
35+
absl::AnyInvocable<void(std::vector<absl::StatusOr<std::string>>) &&>;
36+
37+
struct HTTPRequest {
38+
std::string url;
39+
// Optional
40+
std::vector<std::string> headers = {};
41+
// Optional
42+
std::string body = "";
43+
44+
// Will include response headers in the response with the specified
45+
// case insensitive name.
46+
// Defaults to empty.
47+
std::vector<std::string> include_headers = {};
48+
49+
struct RedirectConfig {
50+
// Limits redirects to HTTP/HTTPS only.
51+
// Defaults to false.
52+
bool strict_http = false;
53+
54+
// Get redirect URL in response metadata.
55+
// Defaults to false.
56+
bool get_redirect_url = false;
57+
} redirect_config;
58+
};
59+
60+
struct HTTPResponse {
61+
// The pointer to this is used to write the request output.
62+
std::string body;
63+
64+
// Optional. Included if include_headers has values.
65+
absl::flat_hash_map<std::string, absl::StatusOr<std::string>> headers;
66+
67+
// Optional. Included if get_redirect_url is true.
68+
std::string final_url;
69+
};
70+
71+
// Maintains state about the data to upload vi CURL.
72+
struct DataToUpload {
73+
// JSON string to upload.
74+
std::string data;
75+
// First offset in the data that has not yet been uploaded.
76+
int offset = 0;
77+
};
78+
79+
using OnDoneFetchUrlWithMetadata =
80+
absl::AnyInvocable<void(absl::StatusOr<HTTPResponse>) &&>;
81+
using OnDoneFetchUrlsWithMetadata =
82+
absl::AnyInvocable<void(std::vector<absl::StatusOr<HTTPResponse>>) &&>;
83+
84+
// Maintains the information about the socket associated with each curl request.
85+
struct SocketInfo {
86+
// Socket file descriptor.
87+
curl_socket_t sock_fd;
88+
// Last activity recorded on the descriptor.
89+
int activity;
90+
// Event type monitored by libevent's event loop.
91+
struct event tracked_event;
92+
};
93+
94+
// Maximum default number of pending curl requests that are awaiting processing.
95+
constexpr inline int kDefaultMaxCurlPendingRequests = 5000;
96+
// Maximum default wait time that a request can sit in the processing queue,
97+
// after which the request will be removed from the queue.
98+
constexpr inline absl::Duration kDefaultMaxRequestWaitTime =
99+
absl::Milliseconds(500);
100+
// Default number of curl workers to use to process the curl requests.
101+
constexpr inline int kDefaultNumCurlWorkers = 1;
102+
103+
struct MultiCurlHttpFetcherAsyncOptions {
104+
// TODO(b/412330778): Maybe these should be absl::Duration
105+
const int64_t keepalive_interval_sec = 2;
106+
const int64_t keepalive_idle_sec = 2;
107+
std::string ca_cert = "/etc/ssl/certs/ca-certificates.crt";
108+
const int64_t curlmopt_maxconnects = 0L;
109+
const int64_t curlmopt_max_total_connections = 0L;
110+
const int64_t curlmopt_max_host_connections = 0L;
111+
int num_curl_workers = kDefaultNumCurlWorkers;
112+
// TODO(b/412330778): Rename to `curl_max_wait_time_ms`
113+
absl::Duration curl_max_wait_time = kDefaultMaxRequestWaitTime;
114+
int curl_queue_length = kDefaultMaxCurlPendingRequests;
115+
};
116+
117+
// This struct maintains the data related to a Curl request, some of which
118+
// has to stay valid throughout the life of the request. The code maintains a
119+
// reference in curl_data_map_ till the request is completed. The destructor
120+
// is then to free the resources in this class after the request completes.
121+
struct CurlRequestData {
122+
explicit CurlRequestData(const std::vector<std::string>& headers,
123+
OnDoneFetchUrlWithMetadata on_done,
124+
std::vector<std::string> response_header_keys,
125+
bool include_redirect_url);
126+
~CurlRequestData();
127+
128+
// The easy handle provided by libcurl, registered to
129+
// multi_curl_request_manager_.
130+
CURL* req_handle;
131+
132+
// The pointer to the linked list of the request HTTP headers.
133+
struct curl_slist* headers_list_ptr = nullptr;
134+
135+
// The callback function for this request from FetchUrl.
136+
OnDoneFetchUrlWithMetadata done_callback;
137+
138+
// Pointer to the body of request. Relevant only for HTTP methods that
139+
// upload data to server.
140+
std::unique_ptr<DataToUpload> body;
141+
142+
// Set response headers in the output.
143+
std::vector<std::string> response_headers;
144+
145+
// Set the final redirect URL in the output.
146+
bool include_redirect_url;
147+
148+
HTTPResponse response_with_metadata;
149+
150+
// Records the time when the request was started.
151+
absl::Time start_time;
152+
};
153+
154+
} // namespace privacy_sandbox::server_common::clients
155+
156+
#endif // SRC_CLIENTS_HTTP_FETCHER_ASYNC_CURL_REQUEST_DATA_H_
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef SRC_CLIENTS_HTTP_FETCHER_ASYNC_HTTP_FETCHER_ASYNC_H_
16+
#define SRC_CLIENTS_HTTP_FETCHER_ASYNC_HTTP_FETCHER_ASYNC_H_
17+
18+
#include <vector>
19+
20+
#include "absl/time/time.h"
21+
#include "src/clients/http_fetcher_async/curl_request_data.h"
22+
23+
namespace privacy_sandbox::server_common::clients {
24+
25+
class HttpFetcherAsync {
26+
public:
27+
HttpFetcherAsync() = default;
28+
virtual ~HttpFetcherAsync() = default;
29+
HttpFetcherAsync(const HttpFetcherAsync&) = delete;
30+
HttpFetcherAsync& operator=(const HttpFetcherAsync&) = delete;
31+
32+
// Fetches the specified url.
33+
//
34+
// http_request: The URL and headers for the HTTP GET request.
35+
// timeout_ms: The request timeout
36+
// done_callback: Output param. Invoked either on error or after finished
37+
// receiving a response. Please note that done_callback will run in a
38+
// threadpool and is not guaranteed to be the FetchUrl client's thread.
39+
// Clients can expect done_callback to be called exactly once.
40+
virtual void FetchUrl(const HTTPRequest& http_request, int timeout_ms,
41+
OnDoneFetchUrl done_callback) = 0;
42+
43+
// Fetches the specified url with response metadata.
44+
//
45+
// http_request: The URL and headers for the HTTP GET request.
46+
// timeout_ms: The request timeout
47+
// done_callback: Output param. Invoked either on error or after finished
48+
// receiving a response. Please note that done_callback will run in a
49+
// threadpool and is not guaranteed to be the FetchUrl client's thread.
50+
// Clients can expect done_callback to be called exactly once.
51+
virtual void FetchUrlWithMetadata(
52+
const HTTPRequest& http_request, int timeout_ms,
53+
OnDoneFetchUrlWithMetadata done_callback) = 0;
54+
55+
// PUTs data to the specified url.
56+
//
57+
// http_request: The URL, headers, body for the HTTP PUT request.
58+
// timeout_ms: The request timeout
59+
// done_callback: Output param. Invoked either on error or after finished
60+
// receiving a response. Please note that done_callback will run in a
61+
// threadpool and is not guaranteed to be the FetchUrl client's thread.
62+
// Clients can expect done_callback to be called exactly once.
63+
virtual void PutUrl(const HTTPRequest& http_request, int timeout_ms,
64+
OnDoneFetchUrl done_callback) = 0;
65+
66+
// Fetches the specified urls.
67+
//
68+
// requests: The URL and headers for the HTTP GET request.
69+
// timeout: The request timeout
70+
// done_callback: Output param. Invoked either on error or after finished
71+
// receiving a response. Please note that done_callback may run in a
72+
// threadpool and is not guaranteed to be the FetchUrl client's thread.
73+
// Clients can expect done_callback to be called exactly once and are
74+
// guaranteed that the order of the results exactly corresponds with the order
75+
// of requests.
76+
virtual void FetchUrls(const std::vector<HTTPRequest>& requests,
77+
absl::Duration timeout,
78+
OnDoneFetchUrls done_callback) = 0;
79+
80+
// Fetches the specified urls with response metadata.
81+
//
82+
// requests: The URL and headers for the HTTP GET request.
83+
// timeout: The request timeout
84+
// done_callback: Output param. Invoked either on error or after finished
85+
// receiving a response. Please note that done_callback may run in a
86+
// threadpool and is not guaranteed to be the FetchUrl client's thread.
87+
// Clients can expect done_callback to be called exactly once and are
88+
// guaranteed that the order of the results exactly corresponds with the order
89+
// of requests.
90+
virtual void FetchUrlsWithMetadata(
91+
const std::vector<HTTPRequest>& requests, absl::Duration timeout,
92+
OnDoneFetchUrlsWithMetadata done_callback) = 0;
93+
};
94+
95+
} // namespace privacy_sandbox::server_common::clients
96+
97+
#endif // SRC_CLIENTS_HTTP_FETCHER_ASYNC_HTTP_FETCHER_ASYNC_H_

0 commit comments

Comments
 (0)