software.amazon.awssdk.services.s3.internal.crossregion.utils.CrossRegionUtils Maven / Gradle / Ivy
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.services.s3.internal.crossregion.utils;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletionException;
import java.util.function.Consumer;
import java.util.function.Supplier;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration;
import software.amazon.awssdk.awscore.exception.AwsErrorDetails;
import software.amazon.awssdk.core.ApiName;
import software.amazon.awssdk.endpoints.EndpointProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.endpoints.S3EndpointProvider;
import software.amazon.awssdk.services.s3.internal.crossregion.endpointprovider.BucketEndpointProvider;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.model.S3Request;
@SdkInternalApi
public final class CrossRegionUtils {
public static final int REDIRECT_STATUS_CODE = 301;
public static final int TEMPORARY_REDIRECT_STATUS_CODE = 307;
public static final String AMZ_BUCKET_REGION_HEADER = "x-amz-bucket-region";
private static final List REDIRECT_STATUS_CODES =
Arrays.asList(REDIRECT_STATUS_CODE, TEMPORARY_REDIRECT_STATUS_CODE);
private static final List REDIRECT_ERROR_CODES = Collections.singletonList("AuthorizationHeaderMalformed");
private static final ApiName API_NAME = ApiName.builder().version("cross-region").name("hll").build();
private static final Consumer USER_AGENT_APPLIER = b -> b.addApiName(API_NAME);
private CrossRegionUtils() {
}
public static Optional getBucketRegionFromException(S3Exception exception) {
return exception.awsErrorDetails()
.sdkHttpResponse()
.firstMatchingHeader(AMZ_BUCKET_REGION_HEADER);
}
public static boolean isS3RedirectException(Throwable exception) {
Throwable exceptionToBeChecked = exception instanceof CompletionException ? exception.getCause() : exception;
return exceptionToBeChecked instanceof S3Exception
&& isRedirectError((S3Exception) exceptionToBeChecked);
}
private static boolean isRedirectError(S3Exception exceptionToBeChecked) {
if (REDIRECT_STATUS_CODES.stream().anyMatch(status -> status.equals(exceptionToBeChecked.statusCode()))) {
return true;
}
if (getBucketRegionFromException(exceptionToBeChecked).isPresent()) {
return true;
}
AwsErrorDetails awsErrorDetails = exceptionToBeChecked.awsErrorDetails();
return awsErrorDetails != null
&& REDIRECT_ERROR_CODES.stream().anyMatch(code -> code.equals(awsErrorDetails.errorCode()));
}
@SuppressWarnings("unchecked")
public static T requestWithDecoratedEndpointProvider(T request, Supplier regionSupplier,
EndpointProvider clientEndpointProvider) {
AwsRequestOverrideConfiguration requestOverrideConfig =
request.overrideConfiguration().orElseGet(() -> AwsRequestOverrideConfiguration.builder().build());
S3EndpointProvider delegateEndpointProvider = (S3EndpointProvider) requestOverrideConfig.endpointProvider()
.orElse(clientEndpointProvider);
return (T) request.toBuilder()
.overrideConfiguration(
requestOverrideConfig.toBuilder()
.endpointProvider(
BucketEndpointProvider.create(delegateEndpointProvider, regionSupplier))
.build())
.build();
}
public static AwsRequestOverrideConfiguration updateUserAgentInConfig(T request) {
return
request.overrideConfiguration().map(c -> c.toBuilder()
.applyMutation(USER_AGENT_APPLIER)
.build())
.orElseGet(() -> AwsRequestOverrideConfiguration.builder()
.applyMutation(USER_AGENT_APPLIER)
.build());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy