From 2d08b1f41499ec37a03c632a648472f3627f5174 Mon Sep 17 00:00:00 2001 From: "Bala.FA" Date: Sun, 26 Jan 2025 10:23:58 +0530 Subject: [PATCH] Add {get,set,delete}BucketCors APIs Signed-off-by: Bala.FA --- .../java/io/minio/DeleteBucketCorsArgs.java | 30 ++++ .../main/java/io/minio/GetBucketCorsArgs.java | 29 ++++ .../main/java/io/minio/MinioAsyncClient.java | 128 ++++++++++++++++++ api/src/main/java/io/minio/MinioClient.java | 121 +++++++++++++++++ .../main/java/io/minio/SetBucketCorsArgs.java | 67 +++++++++ .../io/minio/messages/CORSConfiguration.java | 111 +++++++++++++++ examples/DeleteBucketCors.java | 49 +++++++ examples/GetBucketCors.java | 51 +++++++ examples/SetBucketCors.java | 75 ++++++++++ functional/FunctionalTest.java | 74 ++++++++++ 10 files changed, 735 insertions(+) create mode 100644 api/src/main/java/io/minio/DeleteBucketCorsArgs.java create mode 100644 api/src/main/java/io/minio/GetBucketCorsArgs.java create mode 100644 api/src/main/java/io/minio/SetBucketCorsArgs.java create mode 100644 api/src/main/java/io/minio/messages/CORSConfiguration.java create mode 100644 examples/DeleteBucketCors.java create mode 100644 examples/GetBucketCors.java create mode 100644 examples/SetBucketCors.java diff --git a/api/src/main/java/io/minio/DeleteBucketCorsArgs.java b/api/src/main/java/io/minio/DeleteBucketCorsArgs.java new file mode 100644 index 000000000..b56679da8 --- /dev/null +++ b/api/src/main/java/io/minio/DeleteBucketCorsArgs.java @@ -0,0 +1,30 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2020 MinIO, Inc. + * + * Licensed 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +package io.minio; + +/** + * Argument class of {@link MinioAsyncClient#deleteBucketCors} and {@link + * MinioClient#deleteBucketCors}. + */ +public class DeleteBucketCorsArgs extends BucketArgs { + public static Builder builder() { + return new Builder(); + } + + /** Argument builder of {@link DeleteBucketCorsArgs}. */ + public static final class Builder extends BucketArgs.Builder {} +} diff --git a/api/src/main/java/io/minio/GetBucketCorsArgs.java b/api/src/main/java/io/minio/GetBucketCorsArgs.java new file mode 100644 index 000000000..477310038 --- /dev/null +++ b/api/src/main/java/io/minio/GetBucketCorsArgs.java @@ -0,0 +1,29 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2020 MinIO, Inc. + * + * Licensed 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +package io.minio; + +/** + * Argument class of {@link MinioAsyncClient#getBucketCors} and {@link MinioClient#getBucketCors}. + */ +public class GetBucketCorsArgs extends BucketArgs { + public static Builder builder() { + return new Builder(); + } + + /** Argument builder of {@link GetBucketCorsArgs}. */ + public static final class Builder extends BucketArgs.Builder {} +} diff --git a/api/src/main/java/io/minio/MinioAsyncClient.java b/api/src/main/java/io/minio/MinioAsyncClient.java index ce9430b4d..b30559ce9 100644 --- a/api/src/main/java/io/minio/MinioAsyncClient.java +++ b/api/src/main/java/io/minio/MinioAsyncClient.java @@ -33,6 +33,7 @@ import io.minio.http.HttpUtils; import io.minio.http.Method; import io.minio.messages.Bucket; +import io.minio.messages.CORSConfiguration; import io.minio.messages.CopyObjectResult; import io.minio.messages.CreateBucketConfiguration; import io.minio.messages.DeleteError; @@ -3151,6 +3152,133 @@ public CompletableFuture deleteObjectTags(DeleteObjectTagsArgs args) return executeDeleteAsync(args, null, queryParams).thenAccept(response -> response.close()); } + /** + * Gets CORS configuration of a bucket. + * + *
Example:{@code
+   * CompletableFuture future =
+   *     minioAsyncClient.getBucketCors(GetBucketCorsArgs.builder().bucket("my-bucketname").build());
+   * }
+ * + * @param args {@link GetBucketCorsArgs} object. + * @return {@link CompletableFuture}<{@link CORSConfiguration}> object. + * @throws InsufficientDataException thrown to indicate not enough data available in InputStream. + * @throws InternalException thrown to indicate internal library error. + * @throws InvalidKeyException thrown to indicate missing of HMAC SHA-256 library. + * @throws IOException thrown to indicate I/O error on S3 operation. + * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. + * @throws XmlParserException thrown to indicate XML parsing error. + */ + public CompletableFuture getBucketCors(GetBucketCorsArgs args) + throws InsufficientDataException, InternalException, InvalidKeyException, IOException, + NoSuchAlgorithmException, XmlParserException { + checkArgs(args); + return executeGetAsync(args, null, newMultimap("cors", "")) + .exceptionally( + e -> { + Throwable ex = e.getCause(); + + if (ex instanceof CompletionException) { + ex = ((CompletionException) ex).getCause(); + } + + if (ex instanceof ExecutionException) { + ex = ((ExecutionException) ex).getCause(); + } + + if (ex instanceof ErrorResponseException) { + if (((ErrorResponseException) ex).errorResponse().code().equals("NoSuchTagSet")) { + return null; + } + } + throw new CompletionException(ex); + }) + .thenApply( + response -> { + if (response == null) return new CORSConfiguration(null); + try { + return Xml.unmarshal(CORSConfiguration.class, response.body().charStream()); + } catch (XmlParserException e) { + throw new CompletionException(e); + } finally { + response.close(); + } + }); + } + + /** + * Sets CORS configuration to a bucket. + * + *
Example:{@code
+   * CORSConfiguration config =
+   *     new CORSConfiguration(
+   *         Arrays.asList(
+   *             new CORSConfiguration.CORSRule[] {
+   *               // Rule 1
+   *               new CORSConfiguration.CORSRule(
+   *                   Arrays.asList(new String[] {"*"}), // Allowed headers
+   *                   Arrays.asList(new String[] {"PUT", "POST", "DELETE"}), // Allowed methods
+   *                   Arrays.asList(new String[] {"http://www.example.com"}), // Allowed origins
+   *                   Arrays.asList(
+   *                       new String[] {"x-amz-server-side-encryption"}), // Expose headers
+   *                   null, // ID
+   *                   3000), // Maximum age seconds
+   *               // Rule 2
+   *               new CORSConfiguration.CORSRule(
+   *                   null, // Allowed headers
+   *                   Arrays.asList(new String[] {"GET"}), // Allowed methods
+   *                   Arrays.asList(new String[] {"*"}), // Allowed origins
+   *                   null, // Expose headers
+   *                   null, // ID
+   *                   null // Maximum age seconds
+   *                   )
+   *             }));
+   * CompletableFuture future = minioAsyncClient.setBucketCors(
+   *     SetBucketCorsArgs.builder().bucket("my-bucketname").config(config).build());
+   * }
+ * + * @param args {@link SetBucketCorsArgs} object. + * @return {@link CompletableFuture}<{@link Void}> object. + * @throws InsufficientDataException thrown to indicate not enough data available in InputStream. + * @throws InternalException thrown to indicate internal library error. + * @throws InvalidKeyException thrown to indicate missing of HMAC SHA-256 library. + * @throws IOException thrown to indicate I/O error on S3 operation. + * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. + * @throws XmlParserException thrown to indicate XML parsing error. + */ + public CompletableFuture setBucketCors(SetBucketCorsArgs args) + throws InsufficientDataException, InternalException, InvalidKeyException, IOException, + NoSuchAlgorithmException, XmlParserException { + checkArgs(args); + return executePutAsync(args, null, newMultimap("cors", ""), args.config(), 0) + .thenAccept(response -> response.close()); + } + + /** + * Deletes CORS configuration of a bucket. + * + *
Example:{@code
+   * CompletableFuture future = minioAsyncClient.deleteBucketCors(
+   *     DeleteBucketCorsArgs.builder().bucket("my-bucketname").build());
+   * }
+ * + * @param args {@link DeleteBucketCorsArgs} object. + * @return {@link CompletableFuture}<{@link Void}> object. + * @throws InsufficientDataException thrown to indicate not enough data available in InputStream. + * @throws InternalException thrown to indicate internal library error. + * @throws InvalidKeyException thrown to indicate missing of HMAC SHA-256 library. + * @throws IOException thrown to indicate I/O error on S3 operation. + * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. + * @throws XmlParserException thrown to indicate XML parsing error. + */ + public CompletableFuture deleteBucketCors(DeleteBucketCorsArgs args) + throws InsufficientDataException, InternalException, InvalidKeyException, IOException, + NoSuchAlgorithmException, XmlParserException { + checkArgs(args); + return executeDeleteAsync(args, null, newMultimap("cors", "")) + .thenAccept(response -> response.close()); + } + /** * Uploads multiple objects in a single put call. It is done by creating intermediate TAR file * optionally compressed which is uploaded to S3 service. diff --git a/api/src/main/java/io/minio/MinioClient.java b/api/src/main/java/io/minio/MinioClient.java index dbef78c11..e25baa987 100644 --- a/api/src/main/java/io/minio/MinioClient.java +++ b/api/src/main/java/io/minio/MinioClient.java @@ -27,6 +27,7 @@ import io.minio.errors.ServerException; import io.minio.errors.XmlParserException; import io.minio.messages.Bucket; +import io.minio.messages.CORSConfiguration; import io.minio.messages.DeleteError; import io.minio.messages.Item; import io.minio.messages.LifecycleConfiguration; @@ -2275,6 +2276,126 @@ public void deleteObjectTags(DeleteObjectTagsArgs args) } } + /** + * Gets CORS configuration of a bucket. + * + *
Example:{@code
+   * CORSConfiguration config =
+   *     minioClient.getBucketCors(GetBucketCorsArgs.builder().bucket("my-bucketname").build());
+   * }
+ * + * @param args {@link GetBucketCorsArgs} object. + * @return {@link CORSConfiguration} - CORSConfiguration. + * @throws ErrorResponseException thrown to indicate S3 service returned an error response. + * @throws InsufficientDataException thrown to indicate not enough data available in InputStream. + * @throws InternalException thrown to indicate internal library error. + * @throws InvalidKeyException thrown to indicate missing of HMAC SHA-256 library. + * @throws InvalidResponseException thrown to indicate S3 service returned invalid or no error + * response. + * @throws IOException thrown to indicate I/O error on S3 operation. + * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. + * @throws XmlParserException thrown to indicate XML parsing error. + */ + public CORSConfiguration getBucketCors(GetBucketCorsArgs args) + throws ErrorResponseException, InsufficientDataException, InternalException, + InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, + ServerException, XmlParserException { + try { + return asyncClient.getBucketCors(args).get(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + asyncClient.throwEncapsulatedException(e); + return null; + } + } + + /** + * Sets CORS configuration to a bucket. + * + *
Example:{@code
+   * CORSConfiguration config =
+   *     new CORSConfiguration(
+   *         Arrays.asList(
+   *             new CORSConfiguration.CORSRule[] {
+   *               // Rule 1
+   *               new CORSConfiguration.CORSRule(
+   *                   Arrays.asList(new String[] {"*"}), // Allowed headers
+   *                   Arrays.asList(new String[] {"PUT", "POST", "DELETE"}), // Allowed methods
+   *                   Arrays.asList(new String[] {"http://www.example.com"}), // Allowed origins
+   *                   Arrays.asList(
+   *                       new String[] {"x-amz-server-side-encryption"}), // Expose headers
+   *                   null, // ID
+   *                   3000), // Maximum age seconds
+   *               // Rule 2
+   *               new CORSConfiguration.CORSRule(
+   *                   null, // Allowed headers
+   *                   Arrays.asList(new String[] {"GET"}), // Allowed methods
+   *                   Arrays.asList(new String[] {"*"}), // Allowed origins
+   *                   null, // Expose headers
+   *                   null, // ID
+   *                   null // Maximum age seconds
+   *                   )
+   *             }));
+   * minioClient.setBucketCors(
+   *     SetBucketCorsArgs.builder().bucket("my-bucketname").config(config).build());
+   * }
+ * + * @param args {@link SetBucketCorsArgs} object. + * @throws ErrorResponseException thrown to indicate S3 service returned an error response. + * @throws InsufficientDataException thrown to indicate not enough data available in InputStream. + * @throws InternalException thrown to indicate internal library error. + * @throws InvalidKeyException thrown to indicate missing of HMAC SHA-256 library. + * @throws InvalidResponseException thrown to indicate S3 service returned invalid or no error + * response. + * @throws IOException thrown to indicate I/O error on S3 operation. + * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. + * @throws XmlParserException thrown to indicate XML parsing error. + */ + public void setBucketCors(SetBucketCorsArgs args) + throws ErrorResponseException, InsufficientDataException, InternalException, + InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, + ServerException, XmlParserException { + try { + asyncClient.setBucketCors(args).get(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + asyncClient.throwEncapsulatedException(e); + } + } + + /** + * Deletes CORS configuration of a bucket. + * + *
Example:{@code
+   * minioClient.deleteBucketCors(DeleteBucketCorsArgs.builder().bucket("my-bucketname").build());
+   * }
+ * + * @param args {@link DeleteBucketCorsArgs} object. + * @throws ErrorResponseException thrown to indicate S3 service returned an error response. + * @throws InsufficientDataException thrown to indicate not enough data available in InputStream. + * @throws InternalException thrown to indicate internal library error. + * @throws InvalidKeyException thrown to indicate missing of HMAC SHA-256 library. + * @throws InvalidResponseException thrown to indicate S3 service returned invalid or no error + * response. + * @throws IOException thrown to indicate I/O error on S3 operation. + * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. + * @throws XmlParserException thrown to indicate XML parsing error. + */ + public void deleteBucketCors(DeleteBucketCorsArgs args) + throws ErrorResponseException, InsufficientDataException, InternalException, + InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, + ServerException, XmlParserException { + try { + asyncClient.deleteBucketCors(args).get(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + asyncClient.throwEncapsulatedException(e); + } + } + /** * Uploads multiple objects in a single put call. It is done by creating intermediate TAR file * optionally compressed which is uploaded to S3 service. diff --git a/api/src/main/java/io/minio/SetBucketCorsArgs.java b/api/src/main/java/io/minio/SetBucketCorsArgs.java new file mode 100644 index 000000000..11d6b59ee --- /dev/null +++ b/api/src/main/java/io/minio/SetBucketCorsArgs.java @@ -0,0 +1,67 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2020 MinIO, Inc. + * + * Licensed 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +package io.minio; + +import io.minio.messages.CORSConfiguration; +import java.util.Objects; + +/** + * Argument class of {@link MinioAsyncClient#setBucketCors} and {@link MinioClient#setBucketCors}. + */ +public class SetBucketCorsArgs extends BucketArgs { + private CORSConfiguration config; + + public CORSConfiguration config() { + return config; + } + + public static Builder builder() { + return new Builder(); + } + + /** Argument builder of {@link SetBucketCorsArgs}. */ + public static final class Builder extends BucketArgs.Builder { + private void validateCors(CORSConfiguration config) { + validateNotNull(config, "CORS configuration"); + } + + protected void validate(SetBucketCorsArgs args) { + super.validate(args); + validateCors(args.config); + } + + public Builder config(CORSConfiguration config) { + validateCors(config); + operations.add(args -> args.config = config); + return this; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof SetBucketCorsArgs)) return false; + if (!super.equals(o)) return false; + SetBucketCorsArgs that = (SetBucketCorsArgs) o; + return Objects.equals(config, that.config); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), config); + } +} diff --git a/api/src/main/java/io/minio/messages/CORSConfiguration.java b/api/src/main/java/io/minio/messages/CORSConfiguration.java new file mode 100644 index 000000000..aedc3d253 --- /dev/null +++ b/api/src/main/java/io/minio/messages/CORSConfiguration.java @@ -0,0 +1,111 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2025 MinIO, Inc. + * + * Licensed 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +package io.minio.messages; + +import io.minio.Utils; +import java.util.List; +import javax.annotation.Nullable; +import org.simpleframework.xml.Element; +import org.simpleframework.xml.ElementList; +import org.simpleframework.xml.Namespace; +import org.simpleframework.xml.Root; + +/** + * Object representation of request/response XML of PutBucketCors + * API and GetBucketCors + * API. + */ +@Root(name = "CORSConfiguration", strict = false) +@Namespace(reference = "http://s3.amazonaws.com/doc/2006-03-01/") +public class CORSConfiguration { + @ElementList(name = "CORSRule", inline = true, required = false) + private List rules; + + public CORSConfiguration( + @Nullable @ElementList(name = "CORSRule", required = false) List rules) { + this.rules = rules; + } + + public List rules() { + return Utils.unmodifiableList(rules); + } + + public static class CORSRule { + @ElementList(entry = "AllowedHeader", inline = true, required = false) + private List allowedHeaders; + + @ElementList(entry = "AllowedMethod", inline = true, required = false) + private List allowedMethods; + + @ElementList(entry = "AllowedOrigin", inline = true, required = false) + private List allowedOrigins; + + @ElementList(entry = "ExposeHeader", inline = true, required = false) + private List exposeHeaders; + + @Element(name = "ID", required = false) + private String id; + + @Element(name = "MaxAgeSeconds", required = false) + private Integer maxAgeSeconds; + + public CORSRule( + @Nullable @ElementList(entry = "AllowedHeader", inline = true, required = false) + List allowedHeaders, + @Nullable @ElementList(entry = "AllowedMethod", inline = true, required = false) + List allowedMethods, + @Nullable @ElementList(entry = "AllowedOrigin", inline = true, required = false) + List allowedOrigins, + @Nullable @ElementList(entry = "ExposeHeader", inline = true, required = false) + List exposeHeaders, + @Nullable @Element(name = "ID", required = false) String id, + @Nullable @Element(name = "MaxAgeSeconds", required = false) Integer maxAgeSeconds) { + this.allowedHeaders = allowedHeaders; + this.allowedMethods = allowedMethods; + this.allowedOrigins = allowedOrigins; + this.exposeHeaders = exposeHeaders; + this.id = id; + this.maxAgeSeconds = maxAgeSeconds; + } + + public List allowedHeaders() { + return Utils.unmodifiableList(allowedHeaders); + } + + public List allowedMethods() { + return Utils.unmodifiableList(allowedMethods); + } + + public List allowedOrigins() { + return Utils.unmodifiableList(allowedOrigins); + } + + public List exposeHeaders() { + return Utils.unmodifiableList(exposeHeaders); + } + + public String id() { + return id; + } + + public Integer maxAgeSeconds() { + return maxAgeSeconds; + } + } +} diff --git a/examples/DeleteBucketCors.java b/examples/DeleteBucketCors.java new file mode 100644 index 000000000..86990ab43 --- /dev/null +++ b/examples/DeleteBucketCors.java @@ -0,0 +1,49 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2025 MinIO, Inc. + * + * Licensed 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +import io.minio.DeleteBucketCorsArgs; +import io.minio.MinioClient; +import io.minio.errors.MinioException; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +public class DeleteBucketCors { + /** MinioClient.deleteBucketCors() example. */ + public static void main(String[] args) + throws IOException, NoSuchAlgorithmException, InvalidKeyException { + try { + /* play.min.io for test and development. */ + MinioClient minioClient = + MinioClient.builder() + .endpoint("https://play.min.io") + .credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG") + .build(); + + /* Amazon S3: */ + // MinioClient minioClient = + // MinioClient.builder() + // .endpoint("https://s3.amazonaws.com") + // .credentials("YOUR-ACCESSKEY", "YOUR-SECRETACCESSKEY") + // .build(); + + minioClient.deleteBucketCors(DeleteBucketCorsArgs.builder().bucket("my-bucketname").build()); + System.out.println("Bucket CORS configuration deleted successfully"); + } catch (MinioException e) { + System.out.println("Error occurred: " + e); + } + } +} diff --git a/examples/GetBucketCors.java b/examples/GetBucketCors.java new file mode 100644 index 000000000..713f8fc07 --- /dev/null +++ b/examples/GetBucketCors.java @@ -0,0 +1,51 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2025 MinIO, Inc. + * + * Licensed 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +import io.minio.GetBucketCorsArgs; +import io.minio.MinioClient; +import io.minio.errors.MinioException; +import io.minio.messages.CORSConfiguration; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +public class GetBucketCors { + /** MinioClient.getBucketCors() example. */ + public static void main(String[] args) + throws IOException, NoSuchAlgorithmException, InvalidKeyException { + try { + /* play.min.io for test and development. */ + MinioClient minioClient = + MinioClient.builder() + .endpoint("https://play.min.io") + .credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG") + .build(); + + /* Amazon S3: */ + // MinioClient minioClient = + // MinioClient.builder() + // .endpoint("https://s3.amazonaws.com") + // .credentials("YOUR-ACCESSKEY", "YOUR-SECRETACCESSKEY") + // .build(); + + CORSConfiguration config = + minioClient.getBucketCors(GetBucketCorsArgs.builder().bucket("my-bucketname").build()); + System.out.println("Bucket CORS configuration rules: " + config.rules()); + } catch (MinioException e) { + System.out.println("Error occurred: " + e); + } + } +} diff --git a/examples/SetBucketCors.java b/examples/SetBucketCors.java new file mode 100644 index 000000000..37ec1fcfc --- /dev/null +++ b/examples/SetBucketCors.java @@ -0,0 +1,75 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2020 MinIO, Inc. + * + * Licensed 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 + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +import io.minio.MinioClient; +import io.minio.SetBucketCorsArgs; +import io.minio.errors.MinioException; +import io.minio.messages.CORSConfiguration; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +public class SetBucketCors { + /** MinioClient.setBucketCors() example. */ + public static void main(String[] args) + throws IOException, NoSuchAlgorithmException, InvalidKeyException { + try { + /* play.min.io for test and development. */ + MinioClient minioClient = + MinioClient.builder() + .endpoint("https://play.min.io") + .credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG") + .build(); + + /* Amazon S3: */ + // MinioClient minioClient = + // MinioClient.builder() + // .endpoint("https://s3.amazonaws.com") + // .credentials("YOUR-ACCESSKEY", "YOUR-SECRETACCESSKEY") + // .build(); + + CORSConfiguration config = + new CORSConfiguration( + Arrays.asList( + new CORSConfiguration.CORSRule[] { + // Rule 1 + new CORSConfiguration.CORSRule( + Arrays.asList(new String[] {"*"}), // Allowed headers + Arrays.asList(new String[] {"PUT", "POST", "DELETE"}), // Allowed methods + Arrays.asList(new String[] {"http://www.example.com"}), // Allowed origins + Arrays.asList( + new String[] {"x-amz-server-side-encryption"}), // Expose headers + null, // ID + 3000), // Maximum age seconds + // Rule 2 + new CORSConfiguration.CORSRule( + null, // Allowed headers + Arrays.asList(new String[] {"GET"}), // Allowed methods + Arrays.asList(new String[] {"*"}), // Allowed origins + null, // Expose headers + null, // ID + null // Maximum age seconds + ) + })); + + minioClient.setBucketCors( + SetBucketCorsArgs.builder().bucket("my-bucketname").config(config).build()); + } catch (MinioException e) { + System.out.println("Error occurred: " + e); + } + } +} diff --git a/functional/FunctionalTest.java b/functional/FunctionalTest.java index b4ca17466..4673b2896 100644 --- a/functional/FunctionalTest.java +++ b/functional/FunctionalTest.java @@ -26,6 +26,7 @@ import io.minio.ComposeSource; import io.minio.CopyObjectArgs; import io.minio.CopySource; +import io.minio.DeleteBucketCorsArgs; import io.minio.DeleteBucketEncryptionArgs; import io.minio.DeleteBucketLifecycleArgs; import io.minio.DeleteBucketNotificationArgs; @@ -38,6 +39,7 @@ import io.minio.DisableObjectLegalHoldArgs; import io.minio.DownloadObjectArgs; import io.minio.EnableObjectLegalHoldArgs; +import io.minio.GetBucketCorsArgs; import io.minio.GetBucketEncryptionArgs; import io.minio.GetBucketLifecycleArgs; import io.minio.GetBucketNotificationArgs; @@ -69,6 +71,7 @@ import io.minio.ServerSideEncryptionCustomerKey; import io.minio.ServerSideEncryptionKms; import io.minio.ServerSideEncryptionS3; +import io.minio.SetBucketCorsArgs; import io.minio.SetBucketEncryptionArgs; import io.minio.SetBucketLifecycleArgs; import io.minio.SetBucketNotificationArgs; @@ -92,6 +95,7 @@ import io.minio.http.Method; import io.minio.messages.AndOperator; import io.minio.messages.Bucket; +import io.minio.messages.CORSConfiguration; import io.minio.messages.DeleteMarkerReplication; import io.minio.messages.DeleteObject; import io.minio.messages.Event; @@ -3316,6 +3320,72 @@ public static void deleteBucketEncryption() throws Exception { } } + public static void testBucketCors(String methodName, boolean getTest, boolean deleteTest) + throws Exception { + if (!mintEnv) { + System.out.println(methodName); + } + + long startTime = System.currentTimeMillis(); + String bucketName = getRandomName(); + try { + client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); + try { + CORSConfiguration expectedConfig = + new CORSConfiguration( + Arrays.asList( + new CORSConfiguration.CORSRule[] { + // Rule 1 + new CORSConfiguration.CORSRule( + Arrays.asList(new String[] {"*"}), // Allowed headers + Arrays.asList(new String[] {"PUT", "POST", "DELETE"}), // Allowed methods + Arrays.asList(new String[] {"http://www.example.com"}), // Allowed origins + Arrays.asList( + new String[] {"x-amz-server-side-encryption"}), // Expose headers + null, // ID + 3000), // Maximum age seconds + // Rule 2 + new CORSConfiguration.CORSRule( + null, // Allowed headers + Arrays.asList(new String[] {"GET"}), // Allowed methods + Arrays.asList(new String[] {"*"}), // Allowed origins + null, // Expose headers + null, // ID + null // Maximum age seconds + ) + })); + client.setBucketCors( + SetBucketCorsArgs.builder().bucket(bucketName).config(expectedConfig).build()); + if (getTest) { + CORSConfiguration config = + client.getBucketCors(GetBucketCorsArgs.builder().bucket(bucketName).build()); + Assert.assertEquals( + "cors: expected: " + expectedConfig + ", got: " + config, expectedConfig, config); + } + if (deleteTest) { + client.deleteBucketCors(DeleteBucketCorsArgs.builder().bucket(bucketName).build()); + } + mintSuccessLog(methodName, null, startTime); + } finally { + client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); + } + } catch (Exception e) { + handleException(methodName, null, startTime, e); + } + } + + public static void setBucketCors() throws Exception { + testBucketCors("setBucketCors()", false, false); + } + + public static void getBucketCors() throws Exception { + testBucketCors("getBucketCors()", true, false); + } + + public static void deleteBucketCors() throws Exception { + testBucketCors("deleteBucketCors()", false, true); + } + public static void setBucketTags() throws Exception { String methodName = "setBucketTags()"; if (!mintEnv) { @@ -3720,6 +3790,10 @@ public static void runBucketTests() throws Exception { getBucketEncryption(); deleteBucketEncryption(); + setBucketCors(); + getBucketCors(); + deleteBucketCors(); + setBucketTags(); getBucketTags(); deleteBucketTags();