|
21 | 21 |
|
22 | 22 | #include <format> |
23 | 23 |
|
| 24 | +#include "iceberg/catalog/rest/config.h" |
24 | 25 | #include "iceberg/catalog/rest/constant.h" |
25 | 26 | #include "iceberg/catalog/rest/endpoint_util.h" |
| 27 | +#include "iceberg/result.h" |
26 | 28 | #include "iceberg/util/macros.h" |
27 | 29 |
|
28 | 30 | namespace iceberg::rest { |
29 | 31 |
|
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 |
33 | 35 | auto it = config.configs().find(std::string(RestCatalogConfig::kUri)); |
34 | 36 | if (it == config.configs().end() || it->second.empty()) { |
35 | 37 | return InvalidArgument("Rest catalog configuration property 'uri' is required."); |
36 | 38 | } |
37 | | - return std::string_view(it->second); |
38 | | -} |
39 | | - |
40 | | -} // namespace |
41 | 39 |
|
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 | + } |
43 | 46 |
|
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))); |
47 | 49 | } |
48 | 50 |
|
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)) {} |
53 | 53 |
|
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); |
57 | 59 | } |
58 | 60 |
|
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_); |
63 | 63 | } |
64 | 64 |
|
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_); |
69 | 67 | } |
70 | 68 |
|
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))); |
75 | 73 | } |
76 | 74 |
|
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))); |
81 | 77 | } |
82 | 78 |
|
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))); |
87 | 81 | } |
88 | 82 |
|
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)); |
92 | 86 | } |
93 | 87 |
|
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))); |
98 | 90 | } |
99 | 91 |
|
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)); |
106 | 97 | } |
107 | 98 |
|
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)); |
112 | 102 | } |
113 | 103 |
|
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)); |
119 | 107 | } |
120 | 108 |
|
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)); |
125 | 113 | } |
126 | 114 |
|
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)); |
130 | 118 | } |
131 | 119 |
|
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"); |
136 | 122 | } |
137 | 123 |
|
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))); |
142 | 126 | } |
143 | 127 |
|
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)); |
147 | 131 | } |
148 | 132 |
|
| 133 | +std::string ResourcePaths::V1RenameView() const { return BuildPath("views/rename"); } |
| 134 | + |
149 | 135 | } // namespace iceberg::rest |
0 commit comments