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();

Reply via email to