This is an automated email from the ASF dual-hosted git repository.

ritesh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 0a5fc405e5 HDDS-6440. Handle custom metadata (x-amz-meta) during 
put-object through S3 API. (#3728)
0a5fc405e5 is described below

commit 0a5fc405e52e91f0f1911b5f94d3f912dac8dce7
Author: DaveTeng0 <[email protected]>
AuthorDate: Tue Oct 11 21:26:38 2022 -0700

    HDDS-6440. Handle custom metadata (x-amz-meta) during put-object through S3 
API. (#3728)
---
 .../java/org/apache/hadoop/ozone/OzoneConsts.java  |   2 +
 .../org/apache/hadoop/ozone/client/OzoneKey.java   |  32 +++++--
 .../hadoop/ozone/client/OzoneKeyDetails.java       |  11 +--
 .../apache/hadoop/ozone/client/rpc/RpcClient.java  |   3 +-
 .../dist/src/main/smoketest/s3/commonawslib.robot  |   5 +
 .../dist/src/main/smoketest/s3/objectputget.robot  |  26 +++++
 .../hadoop/ozone/s3/endpoint/EndpointBase.java     |  72 +++++++++++++-
 .../hadoop/ozone/s3/endpoint/ObjectEndpoint.java   |  21 ++--
 .../org/apache/hadoop/ozone/s3/util/S3Consts.java  |   2 +
 .../hadoop/ozone/s3/endpoint/TestEndpointBase.java | 106 +++++++++++++++++++++
 10 files changed, 253 insertions(+), 27 deletions(-)

diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java
index dd01be2a2f..063157fe17 100644
--- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java
+++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java
@@ -392,6 +392,8 @@ public final class OzoneConsts {
 
   public static final int S3_SECRET_KEY_MIN_LENGTH = 8;
 
+  public static final int S3_REQUEST_HEADER_METADATA_SIZE_LIMIT_KB = 2;
+
   //GDPR
   public static final String GDPR_FLAG = "gdprEnabled";
   public static final String GDPR_ALGORITHM_NAME = "AES";
diff --git 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKey.java
 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKey.java
index f0302c8e08..72dfb26f21 100644
--- 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKey.java
+++ 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKey.java
@@ -24,6 +24,8 @@ import org.apache.hadoop.hdds.client.ReplicationFactor;
 import org.apache.hadoop.hdds.client.ReplicationType;
 
 import java.time.Instant;
+import java.util.Map;
+import java.util.HashMap;
 
 /**
  * A class that encapsulates OzoneKey.
@@ -57,6 +59,7 @@ public class OzoneKey {
 
   private ReplicationConfig replicationConfig;
 
+  private Map<String, String> metadata = new HashMap<>();
   /**
    * Constructs OzoneKey from OmKeyInfo.
    *
@@ -67,14 +70,9 @@ public class OzoneKey {
                   String keyName, long size, long creationTime,
                   long modificationTime, ReplicationType type,
                   int replicationFactor) {
-    this.volumeName = volumeName;
-    this.bucketName = bucketName;
-    this.name = keyName;
-    this.dataSize = size;
-    this.creationTime = Instant.ofEpochMilli(creationTime);
-    this.modificationTime = Instant.ofEpochMilli(modificationTime);
-    this.replicationConfig = ReplicationConfig.fromTypeAndFactor(type,
-            ReplicationFactor.valueOf(replicationFactor));
+    this(volumeName, bucketName, keyName, size, creationTime, modificationTime,
+            ReplicationConfig.fromTypeAndFactor(type,
+                    ReplicationFactor.valueOf(replicationFactor)));
   }
 
   /**
@@ -94,6 +92,16 @@ public class OzoneKey {
     this.replicationConfig = replicationConfig;
   }
 
+  @SuppressWarnings("parameternumber")
+  public OzoneKey(String volumeName, String bucketName,
+                  String keyName, long size, long creationTime,
+                  long modificationTime, ReplicationConfig replicationConfig,
+                  Map<String, String> metadata) {
+    this(volumeName, bucketName, keyName, size, creationTime,
+        modificationTime, replicationConfig);
+    this.metadata.putAll(metadata);
+  }
+
   /**
    * Returns Volume Name associated with the Key.
    *
@@ -154,6 +162,14 @@ public class OzoneKey {
    * @return replicationType
    */
 
+  public Map<String, String> getMetadata() {
+    return metadata;
+  }
+
+  public void setMetadata(Map<String, String> metadata) {
+    this.metadata.putAll(metadata);
+  }
+
   @Deprecated
   @JsonIgnore
   public ReplicationType getReplicationType() {
diff --git 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyDetails.java
 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyDetails.java
index 016c34683c..757431bc6b 100644
--- 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyDetails.java
+++ 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneKeyDetails.java
@@ -39,8 +39,6 @@ public class OzoneKeyDetails extends OzoneKey {
    */
   private List<OzoneKeyLocation> ozoneKeyLocations;
 
-  private Map<String, String> metadata;
-
   private FileEncryptionInfo feInfo;
 
   private SupplierWithIOException<OzoneInputStream> contentSupplier;
@@ -58,8 +56,8 @@ public class OzoneKeyDetails extends OzoneKey {
     super(volumeName, bucketName, keyName, size, creationTime,
         modificationTime, type, replicationFactor);
     this.ozoneKeyLocations = ozoneKeyLocations;
-    this.metadata = metadata;
     this.feInfo = feInfo;
+    this.setMetadata(metadata);
   }
 
 
@@ -75,9 +73,8 @@ public class OzoneKeyDetails extends OzoneKey {
       FileEncryptionInfo feInfo,
       SupplierWithIOException<OzoneInputStream> contentSupplier) {
     super(volumeName, bucketName, keyName, size, creationTime,
-            modificationTime, replicationConfig);
+            modificationTime, replicationConfig, metadata);
     this.ozoneKeyLocations = ozoneKeyLocations;
-    this.metadata = metadata;
     this.feInfo = feInfo;
     this.contentSupplier = contentSupplier;
   }
@@ -89,10 +86,6 @@ public class OzoneKeyDetails extends OzoneKey {
     return ozoneKeyLocations;
   }
 
-  public Map<String, String> getMetadata() {
-    return metadata;
-  }
-
   public FileEncryptionInfo getFileEncryptionInfo() {
     return feInfo;
   }
diff --git 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
index 876ed2ade1..973f98ff3b 100644
--- 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
+++ 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
@@ -2002,7 +2002,8 @@ public class RpcClient implements ClientProtocol {
 
     return new OzoneKey(keyInfo.getVolumeName(), keyInfo.getBucketName(),
         keyInfo.getKeyName(), keyInfo.getDataSize(), keyInfo.getCreationTime(),
-        keyInfo.getModificationTime(), keyInfo.getReplicationConfig());
+        keyInfo.getModificationTime(), keyInfo.getReplicationConfig(),
+        keyInfo.getMetadata());
 
   }
 
diff --git a/hadoop-ozone/dist/src/main/smoketest/s3/commonawslib.robot 
b/hadoop-ozone/dist/src/main/smoketest/s3/commonawslib.robot
index 74a3c95a86..375c33d280 100644
--- a/hadoop-ozone/dist/src/main/smoketest/s3/commonawslib.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/s3/commonawslib.robot
@@ -36,6 +36,11 @@ Execute AWSS3APICli and checkrc
     ${output} =       Execute and checkrc        aws s3api --endpoint-url 
${ENDPOINT_URL} ${command}  ${expected_error_code}
     [return]          ${output}
 
+Execute AWSS3APICli and ignore error
+    [Arguments]       ${command}
+    ${output} =       Execute And Ignore Error   aws s3api --endpoint-url 
${ENDPOINT_URL} ${command}
+    [return]          ${output}
+
 Execute AWSS3Cli
     [Arguments]       ${command}
     ${output} =       Execute                     aws s3 --endpoint-url 
${ENDPOINT_URL} ${command}
diff --git a/hadoop-ozone/dist/src/main/smoketest/s3/objectputget.robot 
b/hadoop-ozone/dist/src/main/smoketest/s3/objectputget.robot
index 46608e7357..2f74decb61 100644
--- a/hadoop-ozone/dist/src/main/smoketest/s3/objectputget.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/s3/objectputget.robot
@@ -159,3 +159,29 @@ Zero byte file
 
     ${result} =                 Execute AWSS3APICli and checkrc        
get-object --bucket ${BUCKET} --key ${PREFIX}/putobject/key=value/zerobyte 
--range bytes=0-10000 /tmp/testfile2.result   255
                                 Should contain             ${result}        
InvalidRange
+
+Create file with user defined metadata
+                                Execute                   echo "Randomtext" > 
/tmp/testfile2
+                                Execute AWSS3ApiCli       put-object --bucket 
${BUCKET} --key ${PREFIX}/putobject/custom-metadata/key1 --body /tmp/testfile2 
--metadata="custom-key1=custom-value1,custom-key2=custom-value2"
+
+    ${result} =                 Execute AWSS3APICli       head-object --bucket 
${BUCKET} --key ${PREFIX}/putobject/custom-metadata/key1
+                                Should contain            ${result}    
\"custom-key1\": \"custom-value1\"
+                                Should contain            ${result}    
\"custom-key2\": \"custom-value2\"
+
+    ${result} =                 Execute                   ozone sh key info 
/s3v/${BUCKET}/${PREFIX}/putobject/custom-metadata/key1
+                                Should contain            ${result}   
\"custom-key1\" : \"custom-value1\"
+                                Should contain            ${result}   
\"custom-key2\" : \"custom-value2\"
+
+Create file with user defined metadata with gdpr enabled value in request
+                                Execute                    echo "Randomtext" > 
/tmp/testfile2
+                                Execute AWSS3ApiCli        put-object --bucket 
${BUCKET} --key ${PREFIX}/putobject/custom-metadata/key2 --body /tmp/testfile2 
--metadata="gdprEnabled=true,custom-key2=custom-value2"
+    ${result} =                 Execute AWSS3ApiCli        head-object 
--bucket ${BUCKET} --key ${PREFIX}/putobject/custom-metadata/key2
+                                Should contain             ${result}   
\"custom-key2\": \"custom-value2\"
+                                Should not contain         ${result}   
\"gdprEnabled\": \"true\"
+
+
+Create file with user defined metadata size larger than 2 KB
+                                Execute                    echo "Randomtext" > 
/tmp/testfile2
+    ${custom_metadata_value} =  Execute                    printf 'v%.0s' 
{1..3000}
+    ${result} =                 Execute AWSS3APICli and ignore error        
put-object --bucket ${BUCKET} --key ${PREFIX}/putobject/custom-metadata/key2 
--body /tmp/testfile2 --metadata="custom-key1=${custom_metadata_value}"
+                                Should not contain                          
${result}   custom-key1: ${custom_metadata_value}
diff --git 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
index cc76f267b1..56a187fd00 100644
--- 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
+++ 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
@@ -19,14 +19,24 @@ package org.apache.hadoop.ozone.s3.endpoint;
 
 import javax.annotation.PostConstruct;
 import javax.inject.Inject;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.core.Context;
 import java.io.IOException;
-import java.util.Collections;
-import java.util.Iterator;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Arrays;
 import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Collections;
 import java.util.function.Function;
+import java.util.stream.Collectors;
 
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hadoop.ozone.OzoneConsts;
 import org.apache.hadoop.ozone.audit.AuditAction;
 import org.apache.hadoop.ozone.audit.AuditEventStatus;
 import org.apache.hadoop.ozone.audit.AuditLogger;
@@ -35,6 +45,7 @@ import org.apache.hadoop.ozone.audit.AuditMessage;
 import org.apache.hadoop.ozone.audit.Auditor;
 import org.apache.hadoop.ozone.client.OzoneBucket;
 import org.apache.hadoop.ozone.client.OzoneClient;
+import org.apache.hadoop.ozone.client.OzoneKey;
 import org.apache.hadoop.ozone.client.OzoneVolume;
 import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
 import org.apache.hadoop.ozone.om.exceptions.OMException;
@@ -44,12 +55,16 @@ import org.apache.hadoop.ozone.s3.exception.OS3Exception;
 import org.apache.hadoop.ozone.s3.exception.S3ErrorTable;
 
 import com.google.common.annotations.VisibleForTesting;
+
 import org.apache.hadoop.ozone.s3.metrics.S3GatewayMetrics;
 import org.apache.hadoop.ozone.s3.util.AuditUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.hadoop.ozone.OzoneConsts.KB;
 import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.newError;
+import static 
org.apache.hadoop.ozone.s3.util.S3Consts.CUSTOM_METADATA_HEADER_PREFIX;
 
 /**
  * Basic helpers for all the REST endpoints.
@@ -63,6 +78,8 @@ public abstract class EndpointBase implements Auditor {
   @Context
   private ContainerRequestContext context;
 
+  private Set<String> excludeMetadataFields =
+          new HashSet<>(Arrays.asList(OzoneConsts.GDPR_FLAG));
   private static final Logger LOG =
       LoggerFactory.getLogger(EndpointBase.class);
 
@@ -240,6 +257,57 @@ public abstract class EndpointBase implements Auditor {
     }
   }
 
+  protected Map<String, String> getCustomMetadataFromHeaders(
+      MultivaluedMap<String, String> requestHeaders) throws OS3Exception {
+    Map<String, String> customMetadata = new HashMap<>();
+    if (requestHeaders == null || requestHeaders.isEmpty()) {
+      return customMetadata;
+    }
+
+    Set<String> customMetadataKeys = requestHeaders.keySet().stream()
+            .filter(k -> {
+              if (k.startsWith(CUSTOM_METADATA_HEADER_PREFIX) &&
+                      !excludeMetadataFields.contains(
+                        k.substring(
+                          CUSTOM_METADATA_HEADER_PREFIX.length()))) {
+                return true;
+              }
+              return false;
+            })
+            .collect(Collectors.toSet());
+
+    long sizeInBytes = 0;
+    if (!customMetadataKeys.isEmpty()) {
+      for (String key : customMetadataKeys) {
+        String mapKey =
+            key.substring(CUSTOM_METADATA_HEADER_PREFIX.length());
+        List<String> values = requestHeaders.get(key);
+        String value = StringUtils.join(values, ",");
+        sizeInBytes += mapKey.getBytes(UTF_8).length;
+        sizeInBytes += value.getBytes(UTF_8).length;
+
+        if (sizeInBytes >
+                OzoneConsts.S3_REQUEST_HEADER_METADATA_SIZE_LIMIT_KB * KB) {
+          throw new IllegalArgumentException("Illegal user defined metadata." +
+              " Combined size cannot exceed 2KB.");
+        }
+        customMetadata.put(mapKey, value);
+      }
+    }
+    return customMetadata;
+  }
+
+  protected void addCustomMetadataHeaders(
+      Response.ResponseBuilder responseBuilder, OzoneKey key) {
+
+    Map<String, String> metadata = key.getMetadata();
+    for (Map.Entry<String, String> entry : metadata.entrySet()) {
+      responseBuilder
+          .header(CUSTOM_METADATA_HEADER_PREFIX + entry.getKey(),
+              entry.getValue());
+    }
+  }
+
   private AuditMessage.Builder auditMessageBaseBuilder(AuditAction op,
       Map<String, String> auditMap) {
     AuditMessage.Builder builder = new AuditMessage.Builder()
diff --git 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
index 52df945940..488dc9ce49 100644
--- 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
+++ 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
@@ -48,10 +48,9 @@ import java.text.ParseException;
 import java.time.Instant;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
-import java.util.HashMap;
+import java.util.Map;
 import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.OptionalLong;
 
 import org.apache.commons.lang3.StringUtils;
@@ -210,13 +209,17 @@ public class ObjectEndpoint extends EndpointBase {
             "Connection", "close").build();
       }
 
+      // Normal put object
+      Map<String, String> customMetadata =
+          getCustomMetadataFromHeaders(headers.getRequestHeaders());
+
       if ("STREAMING-AWS4-HMAC-SHA256-PAYLOAD"
           .equals(headers.getHeaderString("x-amz-content-sha256"))) {
         body = new SignedChunksInputStream(body);
       }
 
       output = getClientProtocol().createKey(volume.getName(), bucketName,
-          keyPath, length, replicationConfig, new HashMap<>());
+          keyPath, length, replicationConfig, customMetadata);
       IOUtils.copy(body, output);
 
       getMetrics().incCreateKeySuccess();
@@ -471,6 +474,7 @@ public class ObjectEndpoint extends EndpointBase {
         .header("Content-Length", key.getDataSize())
         .header("Content-Type", "binary/octet-stream");
     addLastModifiedDate(response, key);
+    addCustomMetadataHeaders(response, key);
     getMetrics().incHeadKeySuccess();
     AUDIT.logReadSuccess(buildAuditMessageForSuccess(s3GAction,
         getAuditParameters()));
@@ -883,10 +887,12 @@ public class ObjectEndpoint extends EndpointBase {
 
   void copy(OzoneVolume volume, InputStream src, long srcKeyLen,
       String destKey, String destBucket,
-      ReplicationConfig replication) throws IOException {
-    try (OzoneOutputStream dest = getClientProtocol().createKey(
+      ReplicationConfig replication,
+            Map<String, String> metadata) throws IOException {
+    try (OzoneOutputStream dest =
+                 getClientProtocol().createKey(
         volume.getName(), destBucket, destKey, srcKeyLen,
-        replication, new HashMap<>())) {
+        replication, metadata)) {
       IOUtils.copy(src, dest);
     }
   }
@@ -937,7 +943,8 @@ public class ObjectEndpoint extends EndpointBase {
 
       try (OzoneInputStream src = getClientProtocol().getKey(volume.getName(),
           sourceBucket, sourceKey)) {
-        copy(volume, src, sourceKeyLen, destkey, destBucket, 
replicationConfig);
+        copy(volume, src, sourceKeyLen, destkey, destBucket, replicationConfig,
+                sourceKeyDetails.getMetadata());
       }
 
       final OzoneKeyDetails destKeyDetails = getClientProtocol().getKeyDetails(
diff --git 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Consts.java
 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Consts.java
index f891e13d77..f620fd624c 100644
--- 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Consts.java
+++ 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/S3Consts.java
@@ -62,4 +62,6 @@ public final class S3Consts {
   public static final String S3_XML_NAMESPACE = "http://s3.amazonaws"; +
       ".com/doc/2006-03-01/";
 
+  public static final String CUSTOM_METADATA_HEADER_PREFIX = "x-amz-meta-";
+
 }
diff --git 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestEndpointBase.java
 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestEndpointBase.java
new file mode 100644
index 0000000000..9c1f254b79
--- /dev/null
+++ 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestEndpointBase.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Tests the s3 EndpointBase class methods.
+ */
+package org.apache.hadoop.ozone.s3.endpoint;
+
+import org.apache.hadoop.ozone.OzoneConsts;
+import org.apache.hadoop.ozone.s3.exception.OS3Exception;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+import static 
org.apache.hadoop.ozone.s3.util.S3Consts.CUSTOM_METADATA_HEADER_PREFIX;
+
+/**
+ * Test methods of the EndpointBase.
+ */
+public class TestEndpointBase {
+
+  /**
+   * Verify s3 metadata key "gdprEnabled" can't be set up directly
+   * from the normal client's request,
+   * it should be decided on the server side.
+   */
+  @Test
+  public void testFilterGDPRFromCustomMetadataHeaders()
+          throws OS3Exception {
+    MultivaluedMap<String, String> s3requestHeaders
+            = new MultivaluedHashMap<>();
+    s3requestHeaders.add(
+            CUSTOM_METADATA_HEADER_PREFIX + "custom-key1", "custom-value1");
+    s3requestHeaders.add(
+            CUSTOM_METADATA_HEADER_PREFIX + "custom-key2", "custom-value2");
+    s3requestHeaders.add(
+            CUSTOM_METADATA_HEADER_PREFIX + OzoneConsts.GDPR_FLAG, "true");
+
+    EndpointBase endpointBase = new EndpointBase() {
+      @Override
+      public void init() { }
+    };
+
+    Map<String, String> filteredCustomMetadata =
+            endpointBase.getCustomMetadataFromHeaders(s3requestHeaders);
+    Assert.assertTrue(filteredCustomMetadata.containsKey("custom-key1"));
+    Assert.assertEquals(
+            "custom-value1", filteredCustomMetadata.get("custom-key1"));
+    Assert.assertTrue(filteredCustomMetadata.containsKey("custom-key2"));
+    Assert.assertEquals(
+            "custom-value2", filteredCustomMetadata.get("custom-key2"));
+    Assert.assertFalse(
+            filteredCustomMetadata.containsKey(OzoneConsts.GDPR_FLAG));
+  }
+
+  /**
+   * Verify s3 request metadata size should be smaller than 2 KB.
+   */
+  @Test
+  public void testCustomMetadataHeadersSizeOverbig() {
+    MultivaluedMap<String, String> s3requestHeaders
+            = new MultivaluedHashMap<>();
+    s3requestHeaders.add(
+            CUSTOM_METADATA_HEADER_PREFIX + "custom-key1", "custom-value1");
+    s3requestHeaders.add(
+            CUSTOM_METADATA_HEADER_PREFIX + "custom-key2", "custom-value2");
+    s3requestHeaders.add(
+            CUSTOM_METADATA_HEADER_PREFIX + "custom-key3",
+            new String(new byte[3000], StandardCharsets.UTF_8));
+
+    EndpointBase endpointBase = new EndpointBase() {
+      @Override
+      public void init() { }
+    };
+
+    Exception exception = Assertions.assertThrows(
+            IllegalArgumentException.class,
+            () -> endpointBase.getCustomMetadataFromHeaders(s3requestHeaders));
+    Assert.assertEquals(
+            "Illegal user defined metadata. Combined size cannot exceed 2KB.",
+            exception.getMessage());
+  }
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to