This is an automated email from the ASF dual-hosted git repository.
czy006 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/amoro.git
The following commit(s) were added to refs/heads/master by this push:
new 15cb08da6 [AMORO-4363][ams] Support HEAD route for namespaces in
Iceberg REST catalog (#4364)
15cb08da6 is described below
commit 15cb08da63d85c6783a3f4441b4e006c4501850f
Author: Aakash <[email protected]>
AuthorDate: Tue Sep 8 12:18:04 2026 +0530
[AMORO-4363][ams] Support HEAD route for namespaces in Iceberg REST catalog
(#4364)
---
.../apache/amoro/server/RestCatalogService.java | 6 +++
.../server/TestInternalIcebergCatalogService.java | 51 ++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git
a/amoro-ams/src/main/java/org/apache/amoro/server/RestCatalogService.java
b/amoro-ams/src/main/java/org/apache/amoro/server/RestCatalogService.java
index 4769c5b2c..c271de419 100644
--- a/amoro-ams/src/main/java/org/apache/amoro/server/RestCatalogService.java
+++ b/amoro-ams/src/main/java/org/apache/amoro/server/RestCatalogService.java
@@ -136,6 +136,7 @@ public class RestCatalogService extends PersistentBase
implements RestExtension
get("/v1/catalogs/{catalog}/namespaces", this::listNamespaces);
post("/v1/catalogs/{catalog}/namespaces", this::createNamespace);
get("/v1/catalogs/{catalog}/namespaces/{namespace}",
this::getNamespace);
+ head("/v1/catalogs/{catalog}/namespaces/{namespace}",
this::namespaceExists);
delete("/v1/catalogs/{catalog}/namespaces/{namespace}",
this::dropNamespace);
post(
"/v1/catalogs/{catalog}/namespaces/{namespace}/properties",
@@ -261,6 +262,11 @@ public class RestCatalogService extends PersistentBase
implements RestExtension
.build());
}
+ /** HEAD PREFIX/v1/catalogs/{catalog}/namespaces/{namespace} */
+ public void namespaceExists(Context ctx) {
+ handleNamespace(ctx, (catalog, database) -> null);
+ }
+
/** DELETE PREFIX/v1/catalogs/{catalog}/namespaces/{namespace} */
public void dropNamespace(Context ctx) {
String catalog = ctx.pathParam("catalog");
diff --git
a/amoro-ams/src/test/java/org/apache/amoro/server/TestInternalIcebergCatalogService.java
b/amoro-ams/src/test/java/org/apache/amoro/server/TestInternalIcebergCatalogService.java
index bf810fc11..3ba804d90 100644
---
a/amoro-ams/src/test/java/org/apache/amoro/server/TestInternalIcebergCatalogService.java
+++
b/amoro-ams/src/test/java/org/apache/amoro/server/TestInternalIcebergCatalogService.java
@@ -66,6 +66,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -137,6 +138,56 @@ public class TestInternalIcebergCatalogService extends
RestCatalogServiceTestBas
Assertions.assertTrue(nsCatalog.listNamespaces().isEmpty());
}
+ @Test
+ public void testNamespaceExists() throws IOException, InterruptedException
{
+ HttpClient client = HttpClient.newHttpClient();
+ String existsUrl =
+ ams.getHttpUrl()
+ + restCatalogUri
+ + "/v1/catalogs/"
+ + catalogName()
+ + "/namespaces/"
+ + database;
+ String notExistsUrl =
+ ams.getHttpUrl()
+ + restCatalogUri
+ + "/v1/catalogs/"
+ + catalogName()
+ + "/namespaces/non_existent_db";
+
+ // 1. Verify non-existent namespace returns 404
+ HttpRequest notFoundReq =
+ HttpRequest.newBuilder(URI.create(notExistsUrl))
+ .timeout(Duration.ofSeconds(5))
+ .method("HEAD", HttpRequest.BodyPublishers.noBody())
+ .build();
+ HttpResponse<Void> notFoundResp =
+ client.send(notFoundReq, HttpResponse.BodyHandlers.discarding());
+ Assertions.assertEquals(404, notFoundResp.statusCode());
+ // Note: Iceberg RESTSessionCatalog uses GET fallback unless
Endpoint.V1_NAMESPACE_EXISTS is
+ // advertised in /v1/config
+
Assertions.assertFalse(nsCatalog.namespaceExists(Namespace.of("non_existent_db")));
+
+ // 2. Create namespace and verify HEAD returns 204 No Content
+ nsCatalog.createNamespace(ns);
+ HttpRequest existsReq =
+ HttpRequest.newBuilder(URI.create(existsUrl))
+ .timeout(Duration.ofSeconds(5))
+ .method("HEAD", HttpRequest.BodyPublishers.noBody())
+ .build();
+ HttpResponse<Void> existsResp =
+ client.send(existsReq, HttpResponse.BodyHandlers.discarding());
+ Assertions.assertEquals(204, existsResp.statusCode());
+ Assertions.assertTrue(nsCatalog.namespaceExists(ns));
+
+ // 3. Drop namespace and verify HEAD returns 404 again (full lifecycle
verification)
+ nsCatalog.dropNamespace(ns);
+ HttpResponse<Void> postDropResp =
+ client.send(existsReq, HttpResponse.BodyHandlers.discarding());
+ Assertions.assertEquals(404, postDropResp.statusCode());
+ Assertions.assertFalse(nsCatalog.namespaceExists(ns));
+ }
+
@Test
public void testNamespaceProperties() {
Map<String, String> properties = Maps.newHashMap();