diff --git a/api/src/main/java/io/minio/BucketRegionCache.java b/api/src/main/java/io/minio/AwsRegionCache.java similarity index 64% rename from api/src/main/java/io/minio/BucketRegionCache.java rename to api/src/main/java/io/minio/AwsRegionCache.java index b9f122612..e198d11d6 100644 --- a/api/src/main/java/io/minio/BucketRegionCache.java +++ b/api/src/main/java/io/minio/AwsRegionCache.java @@ -20,38 +20,24 @@ import java.util.concurrent.ConcurrentHashMap; /** A singleton bucket/region cache map. */ -enum BucketRegionCache { +enum AwsRegionCache { INSTANCE; private final Map regionMap = new ConcurrentHashMap<>(); - /** Returns AWS region for given bucket name. */ - public String region(String bucketName) { - if (bucketName == null) { - return "us-east-1"; - } - - String region = this.regionMap.get(bucketName); - if (region == null) { - return "us-east-1"; - } else { - return region; - } - } - - /** Sets bucket name and its region to BucketRegionCache. */ + /** Sets bucket name and its region. */ public void set(String bucketName, String region) { this.regionMap.put(bucketName, region); } - /** Removes region cache of the bucket if any. */ + /** Gets region of bucket name. */ + public String get(String bucketName) { + return this.regionMap.get(bucketName); + } + + /** Removes bucket name and its region. */ public void remove(String bucketName) { if (bucketName != null) { this.regionMap.remove(bucketName); } } - - /** Returns true if given bucket name is in the map else false. */ - public boolean exists(String bucketName) { - return this.regionMap.get(bucketName) != null; - } } diff --git a/api/src/main/java/io/minio/AwsS3Endpoints.java b/api/src/main/java/io/minio/AwsS3Endpoints.java deleted file mode 100644 index 516da6737..000000000 --- a/api/src/main/java/io/minio/AwsS3Endpoints.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2015 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 java.util.HashMap; -import java.util.Map; - -/** Amazon AWS S3 endpoints for various regions. */ -enum AwsS3Endpoints { - INSTANCE; - private final Map endpoints = new HashMap<>(); - - AwsS3Endpoints() { - // ap-northeast-1 - endpoints.put("ap-northeast-1", "s3-ap-northeast-1.amazonaws.com"); - // ap-northeast-2 - endpoints.put("ap-northeast-2", "s3-ap-northeast-2.amazonaws.com"); - // ap-south-1 - endpoints.put("ap-south-1", "s3-ap-south-1.amazonaws.com"); - // ap-southeast-1 - endpoints.put("ap-southeast-1", "s3-ap-southeast-1.amazonaws.com"); - // ap-southeast-2 - endpoints.put("ap-southeast-2", "s3-ap-southeast-2.amazonaws.com"); - // eu-central-1 - endpoints.put("eu-central-1", "s3-eu-central-1.amazonaws.com"); - // eu-west-1 - endpoints.put("eu-west-1", "s3-eu-west-1.amazonaws.com"); - // eu-west-2 - endpoints.put("eu-west-2", "s3-eu-west-2.amazonaws.com"); - // sa-east-1 - endpoints.put("sa-east-1", "s3-sa-east-1.amazonaws.com"); - // us-west-1 - endpoints.put("us-west-1", "s3-us-west-1.amazonaws.com"); - // us-west-2 - endpoints.put("us-west-2", "s3-us-west-2.amazonaws.com"); - // us-east-1 - endpoints.put("us-east-1", "s3.amazonaws.com"); - // us-east-2 - endpoints.put("us-east-2", "s3-us-east-2.amazonaws.com"); - // ca-central-1 - endpoints.put("ca-central-1", "s3.ca-central-1.amazonaws.com"); - // cn-north-1 - endpoints.put("cn-north-1", "s3.cn-north-1.amazonaws.com.cn"); - // cn-northwest-1 - endpoints.put("cn-northwest-1", "s3.cn-northwest-1.amazonaws.com.cn"); - } - - /** Gets Amazon S3 endpoint for the relevant region. */ - public String endpoint(String region) { - String s = AwsS3Endpoints.INSTANCE.endpoints.get(region); - if (s == null) { - s = "s3.amazonaws.com"; - } - return s; - } -} diff --git a/api/src/main/java/io/minio/MinioClient.java b/api/src/main/java/io/minio/MinioClient.java index b6e443213..1276f6210 100755 --- a/api/src/main/java/io/minio/MinioClient.java +++ b/api/src/main/java/io/minio/MinioClient.java @@ -39,7 +39,6 @@ import io.minio.errors.RegionConflictException; import io.minio.errors.XmlParserException; import io.minio.http.Method; -import io.minio.http.Scheme; import io.minio.messages.Bucket; import io.minio.messages.CompleteMultipartUpload; import io.minio.messages.CopyObjectResult; @@ -150,8 +149,8 @@ @SuppressWarnings({"SameParameterValue", "WeakerAccess"}) public class MinioClient { private static final byte[] EMPTY_BODY = new byte[] {}; - // default network I/O timeout is 15 minutes - private static final long DEFAULT_CONNECTION_TIMEOUT = 15 * 60; + // default network I/O timeout is 5 minutes + private static final long DEFAULT_CONNECTION_TIMEOUT = 5; // maximum allowed bucket policy size is 12KiB private static final int MAX_BUCKET_POLICY_SIZE = 12 * 1024; // default expiration for a presigned URL is 7 days in seconds @@ -163,8 +162,6 @@ public class MinioClient { + System.getProperty("os.arch") + ") minio-java/" + MinioProperties.INSTANCE.getVersion(); - private static final String NULL_STRING = "(null)"; - private static final String S3_AMAZONAWS_COM = "s3.amazonaws.com"; private static final String END_HTTP = "----------END-HTTP----------"; private static final String US_EAST_1 = "us-east-1"; private static final String UPLOAD_ID = "uploadId"; @@ -209,6 +206,11 @@ public class MinioClient { private OkHttpClient httpClient; + private boolean isAwsHost = false; + private boolean isAcceleratedHost = false; + private boolean isDualStackHost = false; + private boolean useVirtualStyle = false; + /** * Creates MinIO client object with given endpoint using anonymous access. * @@ -229,8 +231,7 @@ public class MinioClient { * * 192.168.1.60 * * ::1 * - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(URL url) * @see #MinioClient(String endpoint, String accessKey, String secretKey) * @see #MinioClient(String endpoint, String accessKey, String secretKey, String region) @@ -241,11 +242,11 @@ public class MinioClient { * secure) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, * boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ - public MinioClient(String endpoint) throws InvalidEndpointException, InvalidPortException { - this(endpoint, 0, null, null); + public MinioClient(String endpoint) throws IllegalArgumentException { + this(endpoint, null, null, null, null, null, null); } /** @@ -256,8 +257,7 @@ public MinioClient(String endpoint) throws InvalidEndpointException, InvalidPort * } * * @param url Endpoint as {@link URL} object. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(String endpoint, String accessKey, String secretKey) * @see #MinioClient(String endpoint, String accessKey, String secretKey, String region) @@ -268,11 +268,11 @@ public MinioClient(String endpoint) throws InvalidEndpointException, InvalidPort * secure) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, * boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ public MinioClient(URL url) throws InvalidEndpointException, InvalidPortException { - this(url.toString(), 0, null, null); + this(url.toString(), null, null, null, null, null, null); } /** @@ -283,8 +283,7 @@ public MinioClient(URL url) throws InvalidEndpointException, InvalidPortExceptio * } * * @param url Endpoint as {@link HttpUrl} object. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(URL url) * @see #MinioClient(String endpoint, String accessKey, String secretKey) @@ -296,11 +295,11 @@ public MinioClient(URL url) throws InvalidEndpointException, InvalidPortExceptio * secure) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, * boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ - public MinioClient(HttpUrl url) throws InvalidEndpointException, InvalidPortException { - this(url.toString(), 0, null, null); + public MinioClient(HttpUrl url) throws IllegalArgumentException { + this(url.toString(), null, null, null, null, null, null); } /** @@ -326,8 +325,7 @@ public MinioClient(HttpUrl url) throws InvalidEndpointException, InvalidPortExce * * @param accessKey Access key (aka user ID) of your account in S3 service. * @param secretKey Secret Key (aka password) of your account in S3 service. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(URL url) * @see #MinioClient(URL url, String accessKey, String secretKey) @@ -339,12 +337,12 @@ public MinioClient(HttpUrl url) throws InvalidEndpointException, InvalidPortExce * secure) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, * boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ public MinioClient(String endpoint, String accessKey, String secretKey) - throws InvalidEndpointException, InvalidPortException { - this(endpoint, 0, accessKey, secretKey); + throws IllegalArgumentException { + this(endpoint, null, accessKey, secretKey, null, null, null); } /** @@ -371,8 +369,7 @@ public MinioClient(String endpoint, String accessKey, String secretKey) * @param accessKey Access key (aka user ID) of your account in S3 service. * @param secretKey Secret Key (aka password) of your account in S3 service. * @param region Region name of buckets in S3 service. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(URL url) * @see #MinioClient(URL url, String accessKey, String secretKey) @@ -384,18 +381,12 @@ public MinioClient(String endpoint, String accessKey, String secretKey) * secure) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, * boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ public MinioClient(String endpoint, String accessKey, String secretKey, String region) - throws InvalidEndpointException, InvalidPortException { - this( - endpoint, - 0, - accessKey, - secretKey, - region, - !(endpoint != null && endpoint.startsWith("http://"))); + throws IllegalArgumentException { + this(endpoint, null, accessKey, secretKey, region, null, null); } /** @@ -407,8 +398,7 @@ public MinioClient(String endpoint, String accessKey, String secretKey, String r * @param url Endpoint as {@link URL} object. * @param accessKey Access key (aka user ID) of your account in S3 service. * @param secretKey Secret Key (aka password) of your account in S3 service. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(URL url) * @see #MinioClient(String endpoint, String accessKey, String secretKey) @@ -419,12 +409,11 @@ public MinioClient(String endpoint, String accessKey, String secretKey, String r * secure) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, * boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ - public MinioClient(URL url, String accessKey, String secretKey) - throws InvalidEndpointException, InvalidPortException { - this(url.toString(), 0, accessKey, secretKey); + public MinioClient(URL url, String accessKey, String secretKey) throws IllegalArgumentException { + this(url.toString(), null, accessKey, secretKey, null, null, null); } /** @@ -438,8 +427,7 @@ public MinioClient(URL url, String accessKey, String secretKey) * @param url Endpoint as {@link HttpUrl} object. * @param accessKey Access key (aka user ID) of your account in S3 service. * @param secretKey Secret Key (aka password) of your account in S3 service. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(URL url) * @see #MinioClient(String endpoint, String accessKey, String secretKey) @@ -451,12 +439,12 @@ public MinioClient(URL url, String accessKey, String secretKey) * secure) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, * boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ public MinioClient(HttpUrl url, String accessKey, String secretKey) - throws InvalidEndpointException, InvalidPortException { - this(url.toString(), 0, accessKey, secretKey); + throws IllegalArgumentException { + this(url.toString(), null, accessKey, secretKey, null, null, null); } /** @@ -483,8 +471,7 @@ public MinioClient(HttpUrl url, String accessKey, String secretKey) * @param port TCP/IP port number between 1 and 65535. Unused if endpoint is an URL. * @param accessKey Access key (aka user ID) of your account in S3 service. * @param secretKey Secret Key (aka password) of your account in S3 service. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(URL url) * @see #MinioClient(String endpoint, String accessKey, String secretKey) @@ -495,17 +482,12 @@ public MinioClient(HttpUrl url, String accessKey, String secretKey) * secure) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, * boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ public MinioClient(String endpoint, int port, String accessKey, String secretKey) - throws InvalidEndpointException, InvalidPortException { - this( - endpoint, - port, - accessKey, - secretKey, - !(endpoint != null && endpoint.startsWith("http://"))); + throws IllegalArgumentException { + this(endpoint, port, accessKey, secretKey, null, null, null); } /** @@ -533,8 +515,7 @@ public MinioClient(String endpoint, int port, String accessKey, String secretKey * @param accessKey Access key (aka user ID) of your account in S3 service. * @param secretKey Secret Key (aka password) of your account in S3 service. * @param secure Flag to indicate to use secure (TLS) connection to S3 service or not. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(URL url) * @see #MinioClient(String endpoint, String accessKey, String secretKey) @@ -545,12 +526,12 @@ public MinioClient(String endpoint, int port, String accessKey, String secretKey * secure) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, * boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ public MinioClient(String endpoint, String accessKey, String secretKey, boolean secure) - throws InvalidEndpointException, InvalidPortException { - this(endpoint, 0, accessKey, secretKey, secure); + throws IllegalArgumentException { + this(endpoint, null, accessKey, secretKey, null, secure, null); } /** @@ -579,8 +560,7 @@ public MinioClient(String endpoint, String accessKey, String secretKey, boolean * @param accessKey Access key (aka user ID) of your account in S3 service. * @param secretKey Secret Key (aka password) of your account in S3 service. * @param secure Flag to indicate to use secure (TLS) connection to S3 service or not. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(URL url) * @see #MinioClient(String endpoint, String accessKey, String secretKey) @@ -590,12 +570,12 @@ public MinioClient(String endpoint, String accessKey, String secretKey, boolean * @see #MinioClient(String endpoint, String accessKey, String secretKey, boolean secure) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, * boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ public MinioClient(String endpoint, int port, String accessKey, String secretKey, boolean secure) - throws InvalidEndpointException, InvalidPortException { - this(endpoint, port, accessKey, secretKey, null, secure); + throws IllegalArgumentException { + this(endpoint, port, accessKey, secretKey, null, secure, null); } /** @@ -625,8 +605,7 @@ public MinioClient(String endpoint, int port, String accessKey, String secretKey * @param secretKey Secret Key (aka password) of your account in S3 service. * @param region Region name of buckets in S3 service. * @param secure Flag to indicate to use secure (TLS) connection to S3 service or not. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(URL url) * @see #MinioClient(String endpoint, String accessKey, String secretKey) @@ -634,12 +613,12 @@ public MinioClient(String endpoint, int port, String accessKey, String secretKey * @see #MinioClient(URL url, String accessKey, String secretKey) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey) * @see #MinioClient(String endpoint, String accessKey, String secretKey, boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure, OkHttpClient httpClient) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ public MinioClient( String endpoint, int port, String accessKey, String secretKey, String region, boolean secure) - throws InvalidEndpointException, InvalidPortException { + throws IllegalArgumentException { this(endpoint, port, accessKey, secretKey, region, secure, null); } @@ -672,8 +651,7 @@ public MinioClient( * @param region Region name of buckets in S3 service. * @param secure Flag to indicate to use secure (TLS) connection to S3 service or not. * @param httpClient Customized HTTP client object. - * @throws InvalidEndpointException thrown to indicate invalid endpoint passed. - * @throws InvalidPortException thrown to indicate invalid port passed. + * @throws IllegalArgumentException Throws to indicate invalid argument passed. * @see #MinioClient(String endpoint) * @see #MinioClient(URL url) * @see #MinioClient(String endpoint, String accessKey, String secretKey) @@ -681,91 +659,142 @@ public MinioClient( * @see #MinioClient(URL url, String accessKey, String secretKey) * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey) * @see #MinioClient(String endpoint, String accessKey, String secretKey, boolean secure) - * @see #MinioClient(String endpoint, int port, String accessKey, String secretKey, String region, - * boolean secure) + * @see #MinioClient(String endpoint, Integer port, String accessKey, String secretKey, String + * region, Boolean secure, OkHttpClient httpClient) */ public MinioClient( String endpoint, - int port, + Integer port, String accessKey, String secretKey, String region, - boolean secure, + Boolean secure, OkHttpClient httpClient) - throws InvalidEndpointException, InvalidPortException { + throws IllegalArgumentException { if (endpoint == null) { - throw new InvalidEndpointException(NULL_STRING, "null endpoint"); + throw new IllegalArgumentException("null endpoint"); } - if (port < 0 || port > 65535) { - throw new InvalidPortException(port, "port must be in range of 1 to 65535"); - } - - if (httpClient != null) { - this.httpClient = httpClient; - } else { - List protocol = new LinkedList<>(); - protocol.add(Protocol.HTTP_1_1); - this.httpClient = new OkHttpClient(); - this.httpClient = - this.httpClient - .newBuilder() - .connectTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.SECONDS) - .writeTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.SECONDS) - .readTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.SECONDS) - .protocols(protocol) - .build(); + if (region != null && region.equals("")) { + region = null; } + HttpUrl.Builder urlBuilder = null; HttpUrl url = HttpUrl.parse(endpoint); if (url != null) { if (!"/".equals(url.encodedPath())) { - throw new InvalidEndpointException(endpoint, "no path allowed in endpoint"); + throw new IllegalArgumentException("no path allowed in endpoint '" + endpoint + "'"); } - HttpUrl.Builder urlBuilder = url.newBuilder(); - Scheme scheme = Scheme.HTTP; - if (secure) { - scheme = Scheme.HTTPS; + urlBuilder = url.newBuilder(); + } else { + // endpoint may be a valid hostname, IPv4 or IPv6 address + if (!isValidEndpoint(endpoint)) { + throw new IllegalArgumentException("invalid host '" + endpoint + "'"); } - urlBuilder.scheme(scheme.toString()); + urlBuilder = new HttpUrl.Builder().host(endpoint); - if (port > 0) { - urlBuilder.port(port); + if (secure == null) { + secure = Boolean.TRUE; } - - this.baseUrl = urlBuilder.build(); - this.accessKey = accessKey; - this.secretKey = secretKey; - this.region = region; - - return; } - // endpoint may be a valid hostname, IPv4 or IPv6 address - if (!this.isValidEndpoint(endpoint)) { - throw new InvalidEndpointException(endpoint, "invalid host"); + if (secure != null) { + if (secure) { + urlBuilder.scheme("https"); + } else { + urlBuilder.scheme("http"); + } } - Scheme scheme = Scheme.HTTP; - if (secure) { - scheme = Scheme.HTTPS; + if (port != null) { + if (port < 1 || port > 65535) { + throw new IllegalArgumentException("port " + port + " must be in range of 1 to 65535"); + } + + urlBuilder.port(port); } - if (port == 0) { - this.baseUrl = new HttpUrl.Builder().scheme(scheme.toString()).host(endpoint).build(); + url = urlBuilder.build(); + + String host = url.host(); + this.isAwsHost = isAwsEndpoint(host); + boolean isAwsChinaHost = false; + if (this.isAwsHost) { + isAwsChinaHost = host.endsWith(".cn"); + if (isAwsChinaHost) { + urlBuilder.host("amazonaws.com.cn"); + } else { + urlBuilder.host("amazonaws.com"); + } + url = urlBuilder.build(); + + this.isAcceleratedHost = isAwsAccelerateEndpoint(host); + this.isDualStackHost = isAwsDualStackEndpoint(host); + if (region == null) { + region = extractRegion(host); + } + this.useVirtualStyle = true; } else { - this.baseUrl = - new HttpUrl.Builder().scheme(scheme.toString()).host(endpoint).port(port).build(); + this.useVirtualStyle = host.endsWith("aliyuncs.com"); + } + + if (isAwsChinaHost && region == null) { + throw new IllegalArgumentException( + "Region missing in Amazon S3 China endpoint '" + endpoint + "'"); } + + this.region = region; + this.baseUrl = url; this.accessKey = accessKey; this.secretKey = secretKey; - this.region = region; + + if (httpClient == null) { + this.httpClient = + new OkHttpClient() + .newBuilder() + .connectTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MINUTES) + .writeTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MINUTES) + .readTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MINUTES) + .protocols(Arrays.asList(Protocol.HTTP_1_1)) + .build(); + } else { + this.httpClient = httpClient; + } + } + + private static boolean isAwsEndpoint(String endpoint) { + return (endpoint.startsWith("s3.") || endpoint.startsWith("s3-accelerate.")) + && (endpoint.endsWith(".amazonaws.com") || endpoint.endsWith(".amazonaws.com.cn")); + } + + private static boolean isAwsAccelerateEndpoint(String endpoint) { + return endpoint.startsWith("s3-accelerate."); + } + + private static boolean isAwsDualStackEndpoint(String endpoint) { + return endpoint.contains(".dualstack."); + } + + private static String extractRegion(String endpoint) { + String region = null; + String[] tokens = endpoint.split("\\."); + String token = tokens[1]; + + if (token.equals("dualstack")) { + token = tokens[2]; + } + + if (!token.equals("amazonaws")) { + region = token; + } + + return region; } /** Returns true if given endpoint is valid else false. */ - private boolean isValidEndpoint(String endpoint) { + private static boolean isValidEndpoint(String endpoint) { if (InetAddressValidator.getInstance().isValid(endpoint)) { return true; } @@ -791,9 +820,9 @@ private boolean isValidEndpoint(String endpoint) { } /** Validates if given bucket name is DNS compatible. */ - private void checkBucketName(String name) throws InvalidBucketNameException { + private static void checkBucketName(String name) throws InvalidBucketNameException { if (name == null) { - throw new InvalidBucketNameException(NULL_STRING, "null bucket name"); + throw new InvalidBucketNameException("(null)", "null bucket name"); } // Bucket names cannot be no less than 3 and no more than 63 characters long. @@ -817,7 +846,7 @@ private void checkBucketName(String name) throws InvalidBucketNameException { } } - private void checkObjectName(String objectName) throws IllegalArgumentException { + private static void checkObjectName(String objectName) throws IllegalArgumentException { if ((objectName == null) || (objectName.isEmpty())) { throw new IllegalArgumentException("object name cannot be empty"); } @@ -849,7 +878,7 @@ private void checkWriteRequestSse(ServerSideEncryption sse) throws IllegalArgume } } - private Map normalizeHeaders(Map headerMap) { + private static Map normalizeHeaders(Map headerMap) { Map normHeaderMap = new HashMap(); for (Map.Entry entry : headerMap.entrySet()) { String key = entry.getKey(); @@ -873,55 +902,77 @@ private HttpUrl buildUrl( Multimap queryParamMap) throws IllegalArgumentException, InvalidBucketNameException, NoSuchAlgorithmException { if (bucketName == null && objectName != null) { - throw new InvalidBucketNameException( - NULL_STRING, "null bucket name for object '" + objectName + "'"); + throw new IllegalArgumentException("null bucket name for object '" + objectName + "'"); } HttpUrl.Builder urlBuilder = this.baseUrl.newBuilder(); + String host = this.baseUrl.host(); if (bucketName != null) { checkBucketName(bucketName); - String host = this.baseUrl.host(); - if (host.equals(S3_AMAZONAWS_COM)) { - // special case: handle s3.amazonaws.com separately - if (region != null) { - host = AwsS3Endpoints.INSTANCE.endpoint(region); + boolean enforcePathStyle = false; + if (method == Method.PUT && objectName == null && queryParamMap == null) { + // use path style for make bucket to workaround "AuthorizationHeaderMalformed" error from + // s3.amazonaws.com + enforcePathStyle = true; + } else if (queryParamMap != null && queryParamMap.containsKey("location")) { + // use path style for location query + enforcePathStyle = true; + } else if (bucketName.contains(".") && this.baseUrl.isHttps()) { + // use path style where '.' in bucketName causes SSL certificate validation error + enforcePathStyle = true; + } + + if (isAwsHost) { + String s3Domain = "s3."; + if (isAcceleratedHost) { + if (bucketName.contains(".")) { + throw new IllegalArgumentException( + "bucket name '" + + bucketName + + "' with '.' is not allowed for accelerated endpoint"); + } + + if (!enforcePathStyle) { + s3Domain = "s3-accelerate."; + } } - boolean usePathStyle = false; - if (method == Method.PUT && objectName == null && queryParamMap == null) { - // use path style for make bucket to workaround "AuthorizationHeaderMalformed" error from - // s3.amazonaws.com - usePathStyle = true; - } else if (queryParamMap != null && queryParamMap.containsKey("location")) { - // use path style for location query - usePathStyle = true; - } else if (bucketName.contains(".") && this.baseUrl.isHttps()) { - // use path style where '.' in bucketName causes SSL certificate validation error - usePathStyle = true; + String dualStack = ""; + if (isDualStackHost) { + dualStack = "dualstack."; } - if (usePathStyle) { - urlBuilder.host(host); - urlBuilder.addEncodedPathSegment(S3Escaper.encode(bucketName)); - } else { - urlBuilder.host(bucketName + "." + host); + String endpoint = s3Domain + dualStack; + if (enforcePathStyle || !isAcceleratedHost) { + endpoint += region + "."; } - } else { + + host = endpoint + host; + } + + if (enforcePathStyle || !useVirtualStyle) { + urlBuilder.host(host); urlBuilder.addEncodedPathSegment(S3Escaper.encode(bucketName)); + } else { + urlBuilder.host(bucketName + "." + host); } - } - if (objectName != null) { - // Limitation: OkHttp does not allow to add '.' and '..' as path segment. - for (String token : objectName.split("/")) { - if (token.equals(".") || token.equals("..")) { - throw new IllegalArgumentException( - "object name with '.' or '..' path segment is not supported"); + if (objectName != null) { + // Limitation: OkHttp does not allow to add '.' and '..' as path segment. + for (String token : objectName.split("/")) { + if (token.equals(".") || token.equals("..")) { + throw new IllegalArgumentException( + "object name with '.' or '..' path segment is not supported"); + } } - } - urlBuilder.addEncodedPathSegments(S3Escaper.encodePath(objectName)); + urlBuilder.addEncodedPathSegments(S3Escaper.encodePath(objectName)); + } + } else { + if (isAwsHost) { + urlBuilder.host("s3." + region + "." + host); + } } if (queryParamMap != null) { @@ -934,7 +985,7 @@ private HttpUrl buildUrl( return urlBuilder.build(); } - private String getHostHeader(HttpUrl url) { + private static String getHostHeader(HttpUrl url) { // ignore port when port and service matches i.e HTTP -> 80, HTTPS -> 443 if ((url.scheme().equals("http") && url.port() == 80) || (url.scheme().equals("https") && url.port() == 443)) { @@ -1153,7 +1204,8 @@ private Response execute( if (method.equals(Method.HEAD) && bucketName != null && objectName == null - && BucketRegionCache.INSTANCE.exists(bucketName)) { + && isAwsHost + && AwsRegionCache.INSTANCE.get(bucketName) != null) { ec = ErrorCode.RETRY_HEAD_BUCKET; } else { ec = ErrorCode.INVALID_URI; @@ -1203,7 +1255,10 @@ private Response execute( // invalidate region cache if needed if (errorResponse.errorCode() == ErrorCode.NO_SUCH_BUCKET || errorResponse.errorCode() == ErrorCode.RETRY_HEAD_BUCKET) { - BucketRegionCache.INSTANCE.remove(bucketName); + if (isAwsHost) { + AwsRegionCache.INSTANCE.remove(bucketName); + } + // TODO: handle for other cases as well } @@ -1236,50 +1291,43 @@ private Response execute( method, bucketName, objectName, region, headerMultiMap, queryParamMultiMap, body, length); } - /** Updates Region cache for given bucket. */ - private void updateRegionCache(String bucketName) + /** Returns region of given bucket either from region cache or set in constructor. */ + private String getRegion(String bucketName) throws ErrorResponseException, IllegalArgumentException, InsufficientDataException, InternalException, InvalidBucketNameException, InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, XmlParserException { - if (bucketName != null - && this.accessKey != null - && this.secretKey != null - && !BucketRegionCache.INSTANCE.exists(bucketName)) { - Map queryParamMap = new HashMap<>(); - queryParamMap.put("location", null); - - Response response = - execute(Method.GET, bucketName, null, US_EAST_1, null, queryParamMap, null, 0); - - String region; - try (ResponseBody body = response.body()) { - LocationConstraint lc = Xml.unmarshal(LocationConstraint.class, body.charStream()); - if (lc.location() == null || lc.location().equals("")) { - region = US_EAST_1; // default region - } else if (lc.location().equals("EU")) { - region = "eu-west-1"; // eu-west-1 can be sometimes 'EU'. - } else { - region = lc.location(); - } - } + if (this.region != null && !this.region.equals("")) { + return this.region; + } - // Add the new location. - BucketRegionCache.INSTANCE.set(bucketName, region); + if (!isAwsHost || bucketName == null || this.accessKey == null) { + return US_EAST_1; } - } - /** Returns region of given bucket either from region cache or set in constructor. */ - private String getRegion(String bucketName) - throws ErrorResponseException, IllegalArgumentException, InsufficientDataException, - InternalException, InvalidBucketNameException, InvalidKeyException, - InvalidResponseException, IOException, NoSuchAlgorithmException, XmlParserException { - String region; - if (this.region == null || "".equals(this.region)) { - updateRegionCache(bucketName); - region = BucketRegionCache.INSTANCE.region(bucketName); - } else { - region = this.region; + String region = AwsRegionCache.INSTANCE.get(bucketName); + if (region != null) { + return region; } + + // Updates region cache for this bucket. + Map queryParamMap = new HashMap<>(); + queryParamMap.put("location", null); + + Response response = + execute(Method.GET, bucketName, null, US_EAST_1, null, queryParamMap, null, 0); + + try (ResponseBody body = response.body()) { + LocationConstraint lc = Xml.unmarshal(LocationConstraint.class, body.charStream()); + if (lc.location() == null || lc.location().equals("")) { + region = US_EAST_1; + } else if (lc.location().equals("EU")) { + region = "eu-west-1"; // eu-west-1 is also referred as 'EU'. + } else { + region = lc.location(); + } + } + + AwsRegionCache.INSTANCE.set(bucketName, region); return region; } @@ -3283,7 +3331,11 @@ public void makeBucket(String bucketName, String region, boolean objectLock) } Response response = executePut(bucketName, null, region, headerMap, null, config, 0); - response.body().close(); + response.close(); + + if (isAwsHost) { + AwsRegionCache.INSTANCE.set(bucketName, region); + } } /** @@ -4744,7 +4796,7 @@ public SelectResponseStream selectObjectContent( return new SelectResponseStream(response.body().byteStream()); } - private long getAvailableSize(Object data, long expectedReadSize) + private static long getAvailableSize(Object data, long expectedReadSize) throws IOException, InternalException { if (!(data instanceof BufferedInputStream)) { throw new InternalException( @@ -4888,6 +4940,36 @@ public void traceOff() throws IOException { this.traceStream = null; } + /** Enables accelerate endpoint for Amazon S3 endpoint. */ + public void enableAccelerateEndpoint() { + this.isAcceleratedHost = true; + } + + /** Disables accelerate endpoint for Amazon S3 endpoint. */ + public void disableAccelerateEndpoint() { + this.isAcceleratedHost = false; + } + + /** Enables dual-stack endpoint for Amazon S3 endpoint. */ + public void enableDualStackEndpoint() { + this.isDualStackHost = true; + } + + /** Disables dual-stack endpoint for Amazon S3 endpoint. */ + public void disableDualStackEndpoint() { + this.isDualStackHost = false; + } + + /** Enables virtual-style endpoint. */ + public void enableVirtualStyleEndpoint() { + this.useVirtualStyle = true; + } + + /** Disables virtual-style endpoint. */ + public void disableVirtualStyleEndpoint() { + this.useVirtualStyle = false; + } + private static class NotificationResultRecords { Response response = null; Scanner scanner = null; diff --git a/api/src/main/java/io/minio/http/Scheme.java b/api/src/main/java/io/minio/http/Scheme.java index 5518076e6..ff6e21775 100644 --- a/api/src/main/java/io/minio/http/Scheme.java +++ b/api/src/main/java/io/minio/http/Scheme.java @@ -17,6 +17,7 @@ package io.minio.http; /** HTTP schemes. */ +@Deprecated public enum Scheme { HTTP("http"), HTTPS("https"); diff --git a/api/src/test/java/io/minio/MinioClientTest.java b/api/src/test/java/io/minio/MinioClientTest.java index 8f18c61ab..0425e6f84 100644 --- a/api/src/test/java/io/minio/MinioClientTest.java +++ b/api/src/test/java/io/minio/MinioClientTest.java @@ -18,9 +18,7 @@ package io.minio; import io.minio.errors.InvalidBucketNameException; -import io.minio.errors.InvalidEndpointException; import io.minio.errors.InvalidExpiresRangeException; -import io.minio.errors.InvalidPortException; import io.minio.errors.InvalidResponseException; import io.minio.errors.MinioException; import io.minio.errors.RegionConflictException; @@ -43,64 +41,187 @@ public class MinioClientTest { private static final String CONTENT_TYPE = "Content-Type"; private static final String CONTENT_LENGTH = "Content-Length"; - @Test(expected = InvalidEndpointException.class) + @Test(expected = IllegalArgumentException.class) public void testEndpoint1() throws MinioException { new MinioClient((String) null); Assert.fail("exception should be thrown"); } - @Test(expected = InvalidEndpointException.class) + @Test(expected = IllegalArgumentException.class) public void testEndpoint2() throws MinioException { new MinioClient("http://play.min.io/mybucket"); Assert.fail("exception should be thrown"); } - @Test(expected = InvalidEndpointException.class) + @Test(expected = IllegalArgumentException.class) public void testEndpoint3() throws MinioException { new MinioClient("minio-.example.com"); Assert.fail("exception should be thrown"); } - @Test(expected = InvalidEndpointException.class) + @Test(expected = IllegalArgumentException.class) public void testEndpoint4() throws MinioException { new MinioClient("-minio.example.com"); Assert.fail("exception should be thrown"); } - @Test(expected = InvalidEndpointException.class) + @Test(expected = IllegalArgumentException.class) public void testEndpoint5() throws MinioException { new MinioClient("minio..example.com"); Assert.fail("exception should be thrown"); } - @Test(expected = InvalidEndpointException.class) + @Test(expected = IllegalArgumentException.class) public void testEndpoint6() throws MinioException { new MinioClient("minio._.com"); Assert.fail("exception should be thrown"); } - @Test(expected = InvalidPortException.class) + @Test(expected = IllegalArgumentException.class) + public void testEndpoint7() throws MinioException { + new MinioClient("https://s3.amazonaws.com.cn"); + Assert.fail("exception should be thrown"); + } + + @Test(expected = IllegalArgumentException.class) public void testPort1() throws MinioException { - new MinioClient("play.min.io", -1, "", "", false); + new MinioClient("play.min.io", 0, "", "", false); Assert.fail("exception should be thrown"); } - @Test(expected = InvalidPortException.class) + @Test(expected = IllegalArgumentException.class) public void testPort2() throws MinioException { new MinioClient("play.min.io", 70000, "", "", false); Assert.fail("exception should be thrown"); } - @Test(expected = InvalidBucketNameException.class) - public void testBucketName1() + @Test + public void testAwsEndpoints() throws NoSuchAlgorithmException, IOException, InvalidKeyException, MinioException { - MinioClient client = new MinioClient("https://play.min.io:9000"); - client.getObjectUrl(null, "myobject"); - Assert.fail("exception should be thrown"); + MinioClient client = null; + String url = null; + + // virtual-style checks. + client = new MinioClient("https://s3.amazonaws.com"); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://mybucket.s3.us-east-1.amazonaws.com/myobject", url); + + client = new MinioClient("https://s3.us-east-2.amazonaws.com", "myaccesskey", "mysecretkey"); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://mybucket.s3.us-east-2.amazonaws.com/myobject", url); + + client = new MinioClient("https://s3-accelerate.amazonaws.com"); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://mybucket.s3-accelerate.amazonaws.com/myobject", url); + + client = + new MinioClient( + "https://s3.dualstack.ca-central-1.amazonaws.com", "myaccesskey", "mysecretkey"); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://mybucket.s3.dualstack.ca-central-1.amazonaws.com/myobject", url); + + client = new MinioClient("https://s3-accelerate.dualstack.amazonaws.com"); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://mybucket.s3-accelerate.dualstack.amazonaws.com/myobject", url); + + // path-style checks. + client = new MinioClient("https://s3.amazonaws.com"); + client.disableVirtualStyleEndpoint(); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://s3.us-east-1.amazonaws.com/mybucket/myobject", url); + + client = new MinioClient("https://s3.us-east-2.amazonaws.com", "myaccesskey", "mysecretkey"); + client.disableVirtualStyleEndpoint(); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://s3.us-east-2.amazonaws.com/mybucket/myobject", url); + + client = new MinioClient("https://s3-accelerate.amazonaws.com"); + client.disableVirtualStyleEndpoint(); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://s3-accelerate.amazonaws.com/mybucket/myobject", url); + + client = + new MinioClient( + "https://s3.dualstack.ca-central-1.amazonaws.com", "myaccesskey", "mysecretkey"); + client.disableVirtualStyleEndpoint(); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://s3.dualstack.ca-central-1.amazonaws.com/mybucket/myobject", url); + + client = new MinioClient("https://s3-accelerate.dualstack.amazonaws.com"); + client.disableVirtualStyleEndpoint(); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://s3-accelerate.dualstack.amazonaws.com/mybucket/myobject", url); + + // China region. + // virtual-style checks. + client = + new MinioClient("https://s3.cn-north-1.amazonaws.com.cn", "myaccesskey", "mysecretkey"); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://mybucket.s3.cn-north-1.amazonaws.com.cn/myobject", url); + + client = + new MinioClient( + "https://s3-accelerate.amazonaws.com.cn", null, null, null, "cn-north-1", null, null); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://mybucket.s3-accelerate.amazonaws.com.cn/myobject", url); + + client = + new MinioClient( + "https://s3.dualstack.cn-northwest-1.amazonaws.com.cn", "myaccesskey", "mysecretkey"); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals( + "https://mybucket.s3.dualstack.cn-northwest-1.amazonaws.com.cn/myobject", url); + + client = + new MinioClient( + "https://s3-accelerate.dualstack.amazonaws.com.cn", + null, + null, + null, + "cn-north-1", + null, + null); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://mybucket.s3-accelerate.dualstack.amazonaws.com.cn/myobject", url); + + // path-style checks. + client = + new MinioClient("https://s3.cn-north-1.amazonaws.com.cn", "myaccesskey", "mysecretkey"); + client.disableVirtualStyleEndpoint(); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://s3.cn-north-1.amazonaws.com.cn/mybucket/myobject", url); + + client = + new MinioClient( + "https://s3-accelerate.amazonaws.com.cn", null, null, null, "cn-north-1", null, null); + client.disableVirtualStyleEndpoint(); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://s3-accelerate.amazonaws.com.cn/mybucket/myobject", url); + + client = + new MinioClient( + "https://s3.dualstack.cn-northwest-1.amazonaws.com.cn", "myaccesskey", "mysecretkey"); + client.disableVirtualStyleEndpoint(); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals( + "https://s3.dualstack.cn-northwest-1.amazonaws.com.cn/mybucket/myobject", url); + + client = + new MinioClient( + "https://s3-accelerate.dualstack.amazonaws.com.cn", + null, + null, + null, + "cn-north-1", + null, + null); + client.disableVirtualStyleEndpoint(); + url = client.getObjectUrl("mybucket", "myobject"); + Assert.assertEquals("https://s3-accelerate.dualstack.amazonaws.com.cn/mybucket/myobject", url); } - @Test(expected = InvalidBucketNameException.class) - public void testBucketName2() + @Test(expected = IllegalArgumentException.class) + public void testBucketName1() throws NoSuchAlgorithmException, IOException, InvalidKeyException, MinioException { MinioClient client = new MinioClient("https://play.min.io:9000"); client.getObjectUrl(null, "myobject"); @@ -108,7 +229,7 @@ public void testBucketName2() } @Test(expected = InvalidBucketNameException.class) - public void testBucketName3() + public void testBucketName2() throws NoSuchAlgorithmException, IOException, InvalidKeyException, MinioException { MinioClient client = new MinioClient("https://play.min.io:9000"); client.getObjectUrl("", "myobject"); @@ -116,7 +237,7 @@ public void testBucketName3() } @Test(expected = InvalidBucketNameException.class) - public void testBucketName4() + public void testBucketName3() throws NoSuchAlgorithmException, IOException, InvalidKeyException, MinioException { MinioClient client = new MinioClient("https://play.min.io:9000"); client.getObjectUrl("a", "myobject"); @@ -124,7 +245,7 @@ public void testBucketName4() } @Test(expected = InvalidBucketNameException.class) - public void testBucketName5() + public void testBucketName4() throws NoSuchAlgorithmException, IOException, InvalidKeyException, MinioException { MinioClient client = new MinioClient("https://play.min.io:9000"); client.getObjectUrl( @@ -133,7 +254,7 @@ public void testBucketName5() } @Test(expected = InvalidBucketNameException.class) - public void testBucketName6() + public void testBucketName5() throws NoSuchAlgorithmException, IOException, InvalidKeyException, MinioException { MinioClient client = new MinioClient("https://play.min.io:9000"); client.getObjectUrl("a..b", "myobject"); @@ -141,7 +262,7 @@ public void testBucketName6() } @Test(expected = InvalidBucketNameException.class) - public void testBucketName7() + public void testBucketName6() throws NoSuchAlgorithmException, IOException, InvalidKeyException, MinioException { MinioClient client = new MinioClient("https://play.min.io:9000"); client.getObjectUrl("a_b", "myobject"); @@ -149,7 +270,7 @@ public void testBucketName7() } @Test(expected = InvalidBucketNameException.class) - public void testBucketName8() + public void testBucketName7() throws NoSuchAlgorithmException, IOException, InvalidKeyException, MinioException { MinioClient client = new MinioClient("https://play.min.io:9000"); client.getObjectUrl("a#b", "myobject"); diff --git a/build.gradle b/build.gradle index bf54b28c2..2a2cb59b9 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ apply plugin: 'io.codearte.nexus-staging' allprojects { group = 'io.minio' - version = '7.0.2' + version = '7.1.0' if (!project.hasProperty('release')) { version += '-DEV' } diff --git a/functional/FunctionalTest.java b/functional/FunctionalTest.java index 36225f65d..44acc81e7 100644 --- a/functional/FunctionalTest.java +++ b/functional/FunctionalTest.java @@ -3873,7 +3873,7 @@ public static void runTests() throws Exception { // SSE_S3 and SSE_KMS only work with endpoint="s3.amazonaws.com" String requestUrl = endpoint; - if (requestUrl.equals("s3.amazonaws.com")) { + if (requestUrl.contains(".amazonaws.com")) { putObject_test14(); putObject_test15(); copyObject_test11();