Skip to content

Commit 1b17be0

Browse files
committed
fix ci
1 parent c3a992c commit 1b17be0

21 files changed

+822
-388
lines changed

src/iceberg/catalog/rest/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
set(ICEBERG_REST_SOURCES
1919
rest_catalog.cc
2020
catalog_properties.cc
21+
error_handlers.cc
2122
http_client.cc
2223
json_internal.cc
23-
resource_paths.cc)
24+
resource_paths.cc
25+
rest_util.cc)
2426

2527
set(ICEBERG_REST_STATIC_BUILD_INTERFACE_LIBS)
2628
set(ICEBERG_REST_SHARED_BUILD_INTERFACE_LIBS)

src/iceberg/catalog/rest/catalog_properties.cc

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,24 @@
1919

2020
#include "iceberg/catalog/rest/catalog_properties.h"
2121

22+
#include <string_view>
23+
2224
namespace iceberg::rest {
2325

24-
std::unique_ptr<RestCatalogConfig> RestCatalogConfig::default_properties() {
25-
return std::make_unique<RestCatalogConfig>();
26+
std::unique_ptr<RestCatalogProperties> RestCatalogProperties::default_properties() {
27+
return std::unique_ptr<RestCatalogProperties>(new RestCatalogProperties());
2628
}
2729

28-
std::unique_ptr<RestCatalogConfig> RestCatalogConfig::FromMap(
30+
std::unique_ptr<RestCatalogProperties> RestCatalogProperties::FromMap(
2931
const std::unordered_map<std::string, std::string>& properties) {
30-
auto rest_catalog_config = std::make_unique<RestCatalogConfig>();
32+
auto rest_catalog_config =
33+
std::unique_ptr<RestCatalogProperties>(new RestCatalogProperties());
3134
rest_catalog_config->configs_ = properties;
3235
return rest_catalog_config;
3336
}
3437

35-
std::unordered_map<std::string, std::string> RestCatalogConfig::ExtractHeaders() const {
38+
std::unordered_map<std::string, std::string> RestCatalogProperties::ExtractHeaders()
39+
const {
3640
std::unordered_map<std::string, std::string> headers;
3741
constexpr std::string_view prefix = "header.";
3842
for (const auto& [key, value] : configs_) {
@@ -47,4 +51,12 @@ std::unordered_map<std::string, std::string> RestCatalogConfig::ExtractHeaders()
4751
return headers;
4852
}
4953

54+
Result<std::string_view> RestCatalogProperties::Uri() const {
55+
auto it = configs_.find(kUri.key());
56+
if (it == configs_.end() || it->second.empty()) {
57+
return InvalidArgument("Rest catalog configuration property 'uri' is required.");
58+
}
59+
return it->second;
60+
}
61+
5062
} // namespace iceberg::rest

src/iceberg/catalog/rest/catalog_properties.h

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,23 @@
2121

2222
#include <memory>
2323
#include <string>
24-
#include <string_view>
2524
#include <unordered_map>
2625

27-
#include <cpr/cprtypes.h>
28-
2926
#include "iceberg/catalog/rest/iceberg_rest_export.h"
27+
#include "iceberg/result.h"
3028
#include "iceberg/util/config.h"
3129

3230
/// \file iceberg/catalog/rest/catalog_properties.h
33-
/// \brief RestCatalogConfig implementation for Iceberg REST API.
31+
/// \brief RestCatalogProperties implementation for Iceberg REST API.
3432

3533
namespace iceberg::rest {
3634

3735
/// \brief Configuration class for a REST Catalog.
38-
class ICEBERG_REST_EXPORT RestCatalogConfig : public ConfigBase<RestCatalogConfig> {
36+
class ICEBERG_REST_EXPORT RestCatalogProperties
37+
: public ConfigBase<RestCatalogProperties> {
3938
public:
4039
template <typename T>
41-
using Entry = const ConfigBase<RestCatalogConfig>::Entry<T>;
40+
using Entry = const ConfigBase<RestCatalogProperties>::Entry<T>;
4241

4342
/// \brief The URI of the REST catalog server.
4443
inline static Entry<std::string> kUri{"uri", ""};
@@ -49,18 +48,28 @@ class ICEBERG_REST_EXPORT RestCatalogConfig : public ConfigBase<RestCatalogConfi
4948
/// \brief The warehouse path.
5049
inline static Entry<std::string> kWarehouse{"warehouse", ""};
5150

52-
/// \brief Create a default RestCatalogConfig instance.
53-
static std::unique_ptr<RestCatalogConfig> default_properties();
51+
/// \brief The optional prefix for REST API paths.
52+
inline static Entry<std::string> kPrefix{"prefix", ""};
53+
54+
/// \brief Create a default RestCatalogProperties instance.
55+
static std::unique_ptr<RestCatalogProperties> default_properties();
5456

55-
/// \brief Create a RestCatalogConfig instance from a map of key-value pairs.
56-
static std::unique_ptr<RestCatalogConfig> FromMap(
57+
/// \brief Create a RestCatalogProperties instance from a map of key-value pairs.
58+
static std::unique_ptr<RestCatalogProperties> FromMap(
5759
const std::unordered_map<std::string, std::string>& properties);
5860

5961
/// \brief Returns HTTP headers to be added to every request.
6062
///
6163
/// This includes any key prefixed with "header." in the properties.
6264
/// \return A map of headers with the prefix removed from the keys.
6365
std::unordered_map<std::string, std::string> ExtractHeaders() const;
66+
67+
/// \brief Get the URI of the REST catalog server.
68+
/// \return The URI if configured, or an error if not set or empty.
69+
Result<std::string_view> Uri() const;
70+
71+
private:
72+
RestCatalogProperties() = default;
6473
};
6574

6675
} // namespace iceberg::rest

src/iceberg/catalog/rest/constant.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ inline const std::string kHeaderXClientVersion = "X-Client-Version";
3434
inline const std::string kHeaderUserAgent = "User-Agent";
3535

3636
inline const std::string kMimeTypeApplicationJson = "application/json";
37+
inline const std::string kMimeTypeFormUrlEncoded = "application/x-www-form-urlencoded";
3738
inline const std::string kUserAgentPrefix = "iceberg-cpp/";
3839
inline const std::string kUserAgent = "iceberg-cpp/" ICEBERG_VERSION_STRING;
3940

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include "iceberg/catalog/rest/error_handlers.h"
21+
22+
#include <string_view>
23+
24+
namespace iceberg::rest {
25+
26+
namespace {
27+
28+
constexpr std::string_view kIllegalArgumentException = "IllegalArgumentException";
29+
constexpr std::string_view kNoSuchNamespaceException = "NoSuchNamespaceException";
30+
constexpr std::string_view kNamespaceNotEmptyException = "NamespaceNotEmptyException";
31+
32+
} // namespace
33+
34+
const std::shared_ptr<DefaultErrorHandler>& DefaultErrorHandler::Instance() {
35+
static const std::shared_ptr<DefaultErrorHandler> instance{new DefaultErrorHandler()};
36+
return instance;
37+
}
38+
39+
Status DefaultErrorHandler::Accept(const ErrorModel& error) const {
40+
switch (error.code) {
41+
case 400:
42+
if (error.type == kIllegalArgumentException) {
43+
return InvalidArgument(error.message);
44+
}
45+
return BadRequest("Malformed request: {}", error.message);
46+
case 401:
47+
return NotAuthorized("Not authorized: {}", error.message);
48+
case 403:
49+
return Forbidden("Forbidden: {}", error.message);
50+
case 405:
51+
case 406:
52+
break;
53+
case 500:
54+
return InternalServerError("Server error: {}: {}", error.type, error.message);
55+
case 501:
56+
return NotSupported(error.message);
57+
case 503:
58+
return ServiceUnavailable("Service unavailable: {}", error.message);
59+
}
60+
61+
return RestError("Unable to process: {}", error.message);
62+
}
63+
64+
const std::shared_ptr<NamespaceErrorHandler>& NamespaceErrorHandler::Instance() {
65+
static const std::shared_ptr<NamespaceErrorHandler> instance{
66+
new NamespaceErrorHandler()};
67+
return instance;
68+
}
69+
70+
Status NamespaceErrorHandler::Accept(const ErrorModel& error) const {
71+
switch (error.code) {
72+
case 400:
73+
if (error.type == kNamespaceNotEmptyException) {
74+
return NamespaceNotEmpty(error.message);
75+
}
76+
return BadRequest("Malformed request: {}", error.message);
77+
case 404:
78+
return NoSuchNamespace(error.message);
79+
case 409:
80+
return AlreadyExists(error.message);
81+
case 422:
82+
return RestError("Unable to process: {}", error.message);
83+
}
84+
85+
return DefaultErrorHandler::Accept(error);
86+
}
87+
88+
const std::shared_ptr<DropNamespaceErrorHandler>& DropNamespaceErrorHandler::Instance() {
89+
static const std::shared_ptr<DropNamespaceErrorHandler> instance{
90+
new DropNamespaceErrorHandler()};
91+
return instance;
92+
}
93+
94+
Status DropNamespaceErrorHandler::Accept(const ErrorModel& error) const {
95+
if (error.code == 409) {
96+
return NamespaceNotEmpty(error.message);
97+
}
98+
99+
return NamespaceErrorHandler::Accept(error);
100+
}
101+
102+
const std::shared_ptr<TableErrorHandler>& TableErrorHandler::Instance() {
103+
static const std::shared_ptr<TableErrorHandler> instance{new TableErrorHandler()};
104+
return instance;
105+
}
106+
107+
Status TableErrorHandler::Accept(const ErrorModel& error) const {
108+
switch (error.code) {
109+
case 404:
110+
if (error.type == kNoSuchNamespaceException) {
111+
return NoSuchNamespace(error.message);
112+
}
113+
return NoSuchTable(error.message);
114+
case 409:
115+
return AlreadyExists(error.message);
116+
}
117+
118+
return DefaultErrorHandler::Accept(error);
119+
}
120+
121+
const std::shared_ptr<ViewErrorHandler>& ViewErrorHandler::Instance() {
122+
static const std::shared_ptr<ViewErrorHandler> instance{new ViewErrorHandler()};
123+
return instance;
124+
}
125+
126+
Status ViewErrorHandler::Accept(const ErrorModel& error) const {
127+
switch (error.code) {
128+
case 404:
129+
if (error.type == kNoSuchNamespaceException) {
130+
return NoSuchNamespace(error.message);
131+
}
132+
return NoSuchView(error.message);
133+
case 409:
134+
return AlreadyExists(error.message);
135+
}
136+
137+
return DefaultErrorHandler::Accept(error);
138+
}
139+
140+
const std::shared_ptr<TableCommitErrorHandler>& TableCommitErrorHandler::Instance() {
141+
static const std::shared_ptr<TableCommitErrorHandler> instance{
142+
new TableCommitErrorHandler()};
143+
return instance;
144+
}
145+
146+
Status TableCommitErrorHandler::Accept(const ErrorModel& error) const {
147+
switch (error.code) {
148+
case 404:
149+
return NoSuchTable(error.message);
150+
case 409:
151+
return CommitFailed("Commit failed: {}", error.message);
152+
case 500:
153+
case 502:
154+
case 503:
155+
case 504:
156+
return CommitStateUnknown("Service failed: {}: {}", error.code, error.message);
157+
}
158+
159+
return DefaultErrorHandler::Accept(error);
160+
}
161+
162+
const std::shared_ptr<ViewCommitErrorHandler>& ViewCommitErrorHandler::Instance() {
163+
static const std::shared_ptr<ViewCommitErrorHandler> instance{
164+
new ViewCommitErrorHandler()};
165+
return instance;
166+
}
167+
168+
Status ViewCommitErrorHandler::Accept(const ErrorModel& error) const {
169+
switch (error.code) {
170+
case 404:
171+
return NoSuchView(error.message);
172+
case 409:
173+
return CommitFailed("Commit failed: {}", error.message);
174+
case 500:
175+
case 502:
176+
case 503:
177+
case 504:
178+
return CommitStateUnknown("Service failed: {}: {}", error.code, error.message);
179+
}
180+
181+
return DefaultErrorHandler::Accept(error);
182+
}
183+
184+
} // namespace iceberg::rest

0 commit comments

Comments
 (0)