Skip to content

Commit d57f512

Browse files
committed
2
1 parent b1d852e commit d57f512

File tree

4 files changed

+121
-129
lines changed

4 files changed

+121
-129
lines changed

src/iceberg/catalog/rest/catalog.cc

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <cpr/cpr.h>
2626

2727
#include "iceberg/catalog/rest/config.h"
28+
#include "iceberg/catalog/rest/constant.h"
2829
#include "iceberg/catalog/rest/endpoint_util.h"
2930
#include "iceberg/catalog/rest/http_client_interal.h"
3031
#include "iceberg/catalog/rest/json_internal.h"
@@ -37,15 +38,12 @@
3738
namespace iceberg::rest {
3839

3940
Result<std::unique_ptr<RestCatalog>> RestCatalog::Make(const RestCatalogConfig& config) {
40-
// Validate that uri is not empty
41-
auto it = config.configs().find(std::string(RestCatalogConfig::kUri));
42-
if (it == config.configs().end() || it->second.empty()) {
43-
return InvalidArgument("Rest catalog configuration property 'uri' is required.");
44-
}
41+
// Create ResourcePaths and validate URI
42+
ICEBERG_ASSIGN_OR_RAISE(auto paths, ResourcePaths::Make(config));
43+
4544
ICEBERG_ASSIGN_OR_RAISE(auto tmp_client, HttpClient::Make(config));
4645

47-
ResourcePaths paths(config);
48-
ICEBERG_ASSIGN_OR_RAISE(const std::string endpoint, paths.V1Config());
46+
const std::string endpoint = paths->V1Config();
4947
cpr::Parameters params;
5048
ICEBERG_ASSIGN_OR_RAISE(const auto& response, tmp_client->Get(endpoint, params));
5149
switch (response.status_code) {
@@ -64,8 +62,9 @@ Result<std::unique_ptr<RestCatalog>> RestCatalog::Make(const RestCatalogConfig&
6462
}
6563
auto final_config = RestCatalogConfig::FromMap(final_props);
6664
ICEBERG_ASSIGN_OR_RAISE(auto client, HttpClient::Make(*final_config));
65+
ICEBERG_ASSIGN_OR_RAISE(auto final_paths, ResourcePaths::Make(*final_config));
6766
return std::unique_ptr<RestCatalog>(new RestCatalog(
68-
std::move(final_config), std::move(client), ResourcePaths(*final_config)));
67+
std::move(final_config), std::move(client), std::move(*final_paths)));
6968
};
7069
default: {
7170
ICEBERG_ASSIGN_OR_RAISE(auto json, FromJsonString(response.text));
@@ -88,16 +87,16 @@ std::string_view RestCatalog::name() const {
8887
}
8988

9089
Result<std::vector<Namespace>> RestCatalog::ListNamespaces(const Namespace& ns) const {
91-
ICEBERG_ASSIGN_OR_RAISE(const std::string endpoint, paths_.V1Namespaces());
90+
const std::string endpoint = paths_.V1Namespaces();
9291
std::vector<Namespace> result;
9392
std::string next_token;
9493
while (true) {
9594
cpr::Parameters params;
9695
if (!ns.levels.empty()) {
97-
params.Add({"parent", EncodeNamespaceForUrl(ns)});
96+
params.Add({std::string(kQueryParamParent), EncodeNamespaceForUrl(ns)});
9897
}
9998
if (!next_token.empty()) {
100-
params.Add({"page_token", next_token});
99+
params.Add({std::string(kQueryParamPageToken), next_token});
101100
}
102101
ICEBERG_ASSIGN_OR_RAISE(const auto& response, client_->Get(endpoint, params));
103102
switch (response.status_code) {

src/iceberg/catalog/rest/constant.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ constexpr std::string_view kClientVersion = "0.14.1";
3838
constexpr std::string_view kUserAgentPrefix = "iceberg-cpp/";
3939
constexpr std::string_view kUserAgent = "iceberg-cpp/" ICEBERG_VERSION_STRING;
4040

41-
constexpr std::string_view kPathV1 = "v1";
41+
constexpr std::string_view kQueryParamParent = "parent";
42+
constexpr std::string_view kQueryParamPageToken = "page_token";
4243

4344
} // namespace iceberg::rest

src/iceberg/catalog/rest/resource_paths.cc

Lines changed: 64 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -21,129 +21,115 @@
2121

2222
#include <format>
2323

24+
#include "iceberg/catalog/rest/config.h"
2425
#include "iceberg/catalog/rest/constant.h"
2526
#include "iceberg/catalog/rest/endpoint_util.h"
27+
#include "iceberg/result.h"
2628
#include "iceberg/util/macros.h"
2729

2830
namespace iceberg::rest {
2931

30-
namespace {
31-
32-
Result<std::string_view> GetBaseUri(const RestCatalogConfig& config) {
32+
Result<std::unique_ptr<ResourcePaths>> ResourcePaths::Make(
33+
const RestCatalogConfig& config) {
34+
// Validate and extract URI
3335
auto it = config.configs().find(std::string(RestCatalogConfig::kUri));
3436
if (it == config.configs().end() || it->second.empty()) {
3537
return InvalidArgument("Rest catalog configuration property 'uri' is required.");
3638
}
37-
return std::string_view(it->second);
38-
}
39-
40-
} // namespace
4139

42-
ResourcePaths::ResourcePaths(const RestCatalogConfig& config) : config_(config) {}
40+
std::string base_uri = std::string(TrimTrailingSlash(it->second));
41+
std::string prefix;
42+
auto prefix_it = config.configs().find("prefix");
43+
if (prefix_it != config.configs().end() && !prefix_it->second.empty()) {
44+
prefix = prefix_it->second;
45+
}
4346

44-
Result<std::string> ResourcePaths::V1Config() const {
45-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
46-
return std::format("{}/{}/config", TrimTrailingSlash(base_uri), kPathV1);
47+
return std::unique_ptr<ResourcePaths>(
48+
new ResourcePaths(std::move(base_uri), std::move(prefix)));
4749
}
4850

49-
Result<std::string> ResourcePaths::V1OAuth2Tokens() const {
50-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
51-
return std::format("{}/{}/oauth/tokens", TrimTrailingSlash(base_uri), kPathV1);
52-
}
51+
ResourcePaths::ResourcePaths(std::string base_uri, std::string prefix)
52+
: base_uri_(std::move(base_uri)), prefix_(std::move(prefix)) {}
5353

54-
Result<std::string> ResourcePaths::V1Namespaces() const {
55-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
56-
return std::format("{}/{}/namespaces", TrimTrailingSlash(base_uri), kPathV1);
54+
std::string ResourcePaths::BuildPath(std::string_view path) const {
55+
if (prefix_.empty()) {
56+
return std::format("{}/v1/{}", base_uri_, path);
57+
}
58+
return std::format("{}/v1/{}/{}", base_uri_, prefix_, path);
5759
}
5860

59-
Result<std::string> ResourcePaths::V1Namespace(const Namespace& ns) const {
60-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
61-
return std::format("{}/{}/namespaces/{}", TrimTrailingSlash(base_uri), kPathV1,
62-
EncodeNamespaceForUrl(ns));
61+
std::string ResourcePaths::V1Config() const {
62+
return std::format("{}/v1/config", base_uri_);
6363
}
6464

65-
Result<std::string> ResourcePaths::V1NamespaceProperties(const Namespace& ns) const {
66-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
67-
return std::format("{}/{}/namespaces/{}/properties", TrimTrailingSlash(base_uri),
68-
kPathV1, EncodeNamespaceForUrl(ns));
65+
std::string ResourcePaths::V1OAuth2Tokens() const {
66+
return std::format("{}/v1/oauth/tokens", base_uri_);
6967
}
7068

71-
Result<std::string> ResourcePaths::V1Tables(const Namespace& ns) const {
72-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
73-
return std::format("{}/{}/namespaces/{}/tables", TrimTrailingSlash(base_uri), kPathV1,
74-
EncodeNamespaceForUrl(ns));
69+
std::string ResourcePaths::V1Namespaces() const { return BuildPath("namespaces"); }
70+
71+
std::string ResourcePaths::V1Namespace(const Namespace& ns) const {
72+
return BuildPath(std::format("namespaces/{}", EncodeNamespaceForUrl(ns)));
7573
}
7674

77-
Result<std::string> ResourcePaths::V1Table(const TableIdentifier& table) const {
78-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
79-
return std::format("{}/{}/namespaces/{}/tables/{}", TrimTrailingSlash(base_uri),
80-
kPathV1, EncodeNamespaceForUrl(table.ns), table.name);
75+
std::string ResourcePaths::V1NamespaceProperties(const Namespace& ns) const {
76+
return BuildPath(std::format("namespaces/{}/properties", EncodeNamespaceForUrl(ns)));
8177
}
8278

83-
Result<std::string> ResourcePaths::V1RegisterTable(const Namespace& ns) const {
84-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
85-
return std::format("{}/{}/namespaces/{}/register", TrimTrailingSlash(base_uri), kPathV1,
86-
EncodeNamespaceForUrl(ns));
79+
std::string ResourcePaths::V1Tables(const Namespace& ns) const {
80+
return BuildPath(std::format("namespaces/{}/tables", EncodeNamespaceForUrl(ns)));
8781
}
8882

89-
Result<std::string> ResourcePaths::V1RenameTable() const {
90-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
91-
return std::format("{}/{}/tables/rename", TrimTrailingSlash(base_uri), kPathV1);
83+
std::string ResourcePaths::V1Table(const TableIdentifier& table) const {
84+
return BuildPath(std::format("namespaces/{}/tables/{}", EncodeNamespaceForUrl(table.ns),
85+
table.name));
9286
}
9387

94-
Result<std::string> ResourcePaths::V1TableMetrics(const TableIdentifier& table) const {
95-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
96-
return std::format("{}/{}/namespaces/{}/tables/{}/metrics", TrimTrailingSlash(base_uri),
97-
kPathV1, EncodeNamespaceForUrl(table.ns), table.name);
88+
std::string ResourcePaths::V1RegisterTable(const Namespace& ns) const {
89+
return BuildPath(std::format("namespaces/{}/register", EncodeNamespaceForUrl(ns)));
9890
}
9991

100-
Result<std::string> ResourcePaths::V1TableCredentials(
101-
const TableIdentifier& table) const {
102-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
103-
return std::format("{}/{}/namespaces/{}/tables/{}/credentials",
104-
TrimTrailingSlash(base_uri), kPathV1,
105-
EncodeNamespaceForUrl(table.ns), table.name);
92+
std::string ResourcePaths::V1RenameTable() const { return BuildPath("tables/rename"); }
93+
94+
std::string ResourcePaths::V1TableMetrics(const TableIdentifier& table) const {
95+
return BuildPath(std::format("namespaces/{}/tables/{}/metrics",
96+
EncodeNamespaceForUrl(table.ns), table.name));
10697
}
10798

108-
Result<std::string> ResourcePaths::V1TableScanPlan(const TableIdentifier& table) const {
109-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
110-
return std::format("{}/{}/namespaces/{}/tables/{}/plan", TrimTrailingSlash(base_uri),
111-
kPathV1, EncodeNamespaceForUrl(table.ns), table.name);
99+
std::string ResourcePaths::V1TableCredentials(const TableIdentifier& table) const {
100+
return BuildPath(std::format("namespaces/{}/tables/{}/credentials",
101+
EncodeNamespaceForUrl(table.ns), table.name));
112102
}
113103

114-
Result<std::string> ResourcePaths::V1TableScanPlanResult(
115-
const TableIdentifier& table, const std::string& plan_id) const {
116-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
117-
return std::format("{}/{}/namespaces/{}/tables/{}/plan/{}", TrimTrailingSlash(base_uri),
118-
kPathV1, EncodeNamespaceForUrl(table.ns), table.name, plan_id);
104+
std::string ResourcePaths::V1TableScanPlan(const TableIdentifier& table) const {
105+
return BuildPath(std::format("namespaces/{}/tables/{}/plan",
106+
EncodeNamespaceForUrl(table.ns), table.name));
119107
}
120108

121-
Result<std::string> ResourcePaths::V1TableTasks(const TableIdentifier& table) const {
122-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
123-
return std::format("{}/{}/namespaces/{}/tables/{}/tasks", TrimTrailingSlash(base_uri),
124-
kPathV1, EncodeNamespaceForUrl(table.ns), table.name);
109+
std::string ResourcePaths::V1TableScanPlanResult(const TableIdentifier& table,
110+
const std::string& plan_id) const {
111+
return BuildPath(std::format("namespaces/{}/tables/{}/plan/{}",
112+
EncodeNamespaceForUrl(table.ns), table.name, plan_id));
125113
}
126114

127-
Result<std::string> ResourcePaths::V1TransactionCommit() const {
128-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
129-
return std::format("{}/{}/transactions/commit", TrimTrailingSlash(base_uri), kPathV1);
115+
std::string ResourcePaths::V1TableTasks(const TableIdentifier& table) const {
116+
return BuildPath(std::format("namespaces/{}/tables/{}/tasks",
117+
EncodeNamespaceForUrl(table.ns), table.name));
130118
}
131119

132-
Result<std::string> ResourcePaths::V1Views(const Namespace& ns) const {
133-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
134-
return std::format("{}/{}/namespaces/{}/views", TrimTrailingSlash(base_uri), kPathV1,
135-
EncodeNamespaceForUrl(ns));
120+
std::string ResourcePaths::V1TransactionCommit() const {
121+
return BuildPath("transactions/commit");
136122
}
137123

138-
Result<std::string> ResourcePaths::V1View(const TableIdentifier& view) const {
139-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
140-
return std::format("{}/{}/namespaces/{}/views/{}", TrimTrailingSlash(base_uri), kPathV1,
141-
EncodeNamespaceForUrl(view.ns), view.name);
124+
std::string ResourcePaths::V1Views(const Namespace& ns) const {
125+
return BuildPath(std::format("namespaces/{}/views", EncodeNamespaceForUrl(ns)));
142126
}
143127

144-
Result<std::string> ResourcePaths::V1RenameView() const {
145-
ICEBERG_ASSIGN_OR_RAISE(auto base_uri, GetBaseUri(config_));
146-
return std::format("{}/{}/views/rename", TrimTrailingSlash(base_uri), kPathV1);
128+
std::string ResourcePaths::V1View(const TableIdentifier& view) const {
129+
return BuildPath(
130+
std::format("namespaces/{}/views/{}", EncodeNamespaceForUrl(view.ns), view.name));
147131
}
148132

133+
std::string ResourcePaths::V1RenameView() const { return BuildPath("views/rename"); }
134+
149135
} // namespace iceberg::rest

src/iceberg/catalog/rest/resource_paths.h

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -39,88 +39,94 @@ class ICEBERG_REST_EXPORT ResourcePaths {
3939
public:
4040
/// \brief Construct a ResourcePaths with REST catalog configuration.
4141
/// \param config The REST catalog configuration containing the base URI
42-
explicit ResourcePaths(const RestCatalogConfig& config);
42+
static Result<std::unique_ptr<ResourcePaths>> Make(const RestCatalogConfig& config);
4343

4444
/// \brief Get the /v1/{prefix}/config endpoint path.
45-
/// \return Result containing the endpoint URL or an error if URI is not configured
46-
Result<std::string> V1Config() const;
45+
/// \return The endpoint URL
46+
std::string V1Config() const;
4747

4848
/// \brief Get the /v1/{prefix}/oauth/tokens endpoint path.
49-
/// \return Result containing the endpoint URL or an error if URI is not configured
50-
Result<std::string> V1OAuth2Tokens() const;
49+
/// \return The endpoint URL
50+
std::string V1OAuth2Tokens() const;
5151

5252
/// \brief Get the /v1/{prefix}/namespaces endpoint path.
53-
/// \return Result containing the endpoint URL or an error if URI is not configured
54-
Result<std::string> V1Namespaces() const;
53+
/// \return The endpoint URL
54+
std::string V1Namespaces() const;
5555

5656
/// \brief Get the /v1/{prefix}/namespaces/{namespace} endpoint path.
57-
/// \return Result containing the endpoint URL or an error if URI is not configured
58-
Result<std::string> V1Namespace(const Namespace& ns) const;
57+
/// \return The endpoint URL
58+
std::string V1Namespace(const Namespace& ns) const;
5959

6060
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/properties endpoint path.
61-
/// \return Result containing the endpoint URL or an error if URI is not configured
62-
Result<std::string> V1NamespaceProperties(const Namespace& ns) const;
61+
/// \return The endpoint URL
62+
std::string V1NamespaceProperties(const Namespace& ns) const;
6363

6464
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/tables endpoint path.
65-
/// \return Result containing the endpoint URL or an error if URI is not configured
66-
Result<std::string> V1Tables(const Namespace& ns) const;
65+
/// \return The endpoint URL
66+
std::string V1Tables(const Namespace& ns) const;
6767

6868
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/tables/{table} endpoint path.
69-
/// \return Result containing the endpoint URL or an error if URI is not configured
70-
Result<std::string> V1Table(const TableIdentifier& table) const;
69+
/// \return The endpoint URL
70+
std::string V1Table(const TableIdentifier& table) const;
7171

7272
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/register endpoint path.
73-
/// \return Result containing the endpoint URL or an error if URI is not configured
74-
Result<std::string> V1RegisterTable(const Namespace& ns) const;
73+
/// \return The endpoint URL
74+
std::string V1RegisterTable(const Namespace& ns) const;
7575

7676
/// \brief Get the /v1/{prefix}/tables/rename endpoint path.
77-
/// \return Result containing the endpoint URL or an error if URI is not configured
78-
Result<std::string> V1RenameTable() const;
77+
/// \return The endpoint URL
78+
std::string V1RenameTable() const;
7979

8080
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/tables/{table}/metrics endpoint
8181
/// path.
82-
/// \return Result containing the endpoint URL or an error if URI is not configured
83-
Result<std::string> V1TableMetrics(const TableIdentifier& table) const;
82+
/// \return The endpoint URL
83+
std::string V1TableMetrics(const TableIdentifier& table) const;
8484

8585
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/tables/{table}/credentials
8686
/// endpoint path.
87-
/// \return Result containing the endpoint URL or an error if URI is not configured
88-
Result<std::string> V1TableCredentials(const TableIdentifier& table) const;
87+
/// \return The endpoint URL
88+
std::string V1TableCredentials(const TableIdentifier& table) const;
8989

9090
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/tables/{table}/plan endpoint
9191
/// path.
92-
/// \return Result containing the endpoint URL or an error if URI is not configured
93-
Result<std::string> V1TableScanPlan(const TableIdentifier& table) const;
92+
/// \return The endpoint URL
93+
std::string V1TableScanPlan(const TableIdentifier& table) const;
9494

9595
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/tables/{table}/plan/{planId}
9696
/// endpoint path.
97-
/// \return Result containing the endpoint URL or an error if URI is not configured
98-
Result<std::string> V1TableScanPlanResult(const TableIdentifier& table,
99-
const std::string& plan_id) const;
97+
/// \return The endpoint URL
98+
std::string V1TableScanPlanResult(const TableIdentifier& table,
99+
const std::string& plan_id) const;
100100

101101
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/tables/{table}/tasks endpoint
102102
/// path.
103-
/// \return Result containing the endpoint URL or an error if URI is not configured
104-
Result<std::string> V1TableTasks(const TableIdentifier& table) const;
103+
/// \return The endpoint URL
104+
std::string V1TableTasks(const TableIdentifier& table) const;
105105

106106
/// \brief Get the /v1/{prefix}/transactions/commit endpoint path.
107-
/// \return Result containing the endpoint URL or an error if URI is not configured
108-
Result<std::string> V1TransactionCommit() const;
107+
/// \return The endpoint URL
108+
std::string V1TransactionCommit() const;
109109

110110
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/views endpoint path.
111-
/// \return Result containing the endpoint URL or an error if URI is not configured
112-
Result<std::string> V1Views(const Namespace& ns) const;
111+
/// \return The endpoint URL
112+
std::string V1Views(const Namespace& ns) const;
113113

114114
/// \brief Get the /v1/{prefix}/namespaces/{namespace}/views/{view} endpoint path.
115-
/// \return Result containing the endpoint URL or an error if URI is not configured
116-
Result<std::string> V1View(const TableIdentifier& view) const;
115+
/// \return The endpoint URL
116+
std::string V1View(const TableIdentifier& view) const;
117117

118118
/// \brief Get the /v1/{prefix}/views/rename endpoint path.
119-
/// \return Result containing the endpoint URL or an error if URI is not configured
120-
Result<std::string> V1RenameView() const;
119+
/// \return The endpoint URL
120+
std::string V1RenameView() const;
121121

122122
private:
123-
const RestCatalogConfig& config_;
123+
explicit ResourcePaths(std::string base_uri, std::string prefix);
124+
125+
// Helper to build path with optional prefix: {base_uri_}/{prefix_?}/{path}
126+
std::string BuildPath(std::string_view path) const;
127+
128+
std::string base_uri_; // URI with /v1, e.g., "http://localhost:8181/v1"
129+
std::string prefix_; // Optional prefix from config
124130
};
125131

126132
} // namespace iceberg::rest

0 commit comments

Comments
 (0)