1 /* 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"). 5 * You may not use this file except in compliance with the License. 6 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 16 package software.amazon.awssdk.services.glacier.internal; 17 18 import software.amazon.awssdk.annotations.SdkInternalApi; 19 import software.amazon.awssdk.core.interceptor.Context; 20 import software.amazon.awssdk.core.interceptor.ExecutionAttributes; 21 import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; 22 import software.amazon.awssdk.http.SdkHttpRequest; 23 import software.amazon.awssdk.services.glacier.model.DescribeJobRequest; 24 import software.amazon.awssdk.services.glacier.model.GetJobOutputRequest; 25 import software.amazon.awssdk.services.glacier.model.UploadMultipartPartRequest; 26 import software.amazon.awssdk.utils.StringUtils; 27 28 @SdkInternalApi 29 public final class GlacierExecutionInterceptor implements ExecutionInterceptor { 30 31 @Override modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes)32 public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { 33 SdkHttpRequest request = context.httpRequest(); 34 Object originalRequest = context.request(); 35 return request.toBuilder() 36 .applyMutation(b -> beforeRequest(originalRequest, b)) 37 .build(); 38 } 39 beforeRequest(Object originalRequest, SdkHttpRequest.Builder mutableRequest)40 private SdkHttpRequest.Builder beforeRequest(Object originalRequest, SdkHttpRequest.Builder mutableRequest) { 41 mutableRequest.putHeader("x-amz-glacier-version", "2012-06-01"); 42 43 // "x-amz-content-sha256" header is required for sig v4 for some streaming operations 44 mutableRequest.putHeader("x-amz-content-sha256", "required"); 45 46 if (originalRequest instanceof UploadMultipartPartRequest) { 47 mutableRequest.firstMatchingHeader("Content-Range") 48 .ifPresent(range -> mutableRequest.putHeader("Content-Length", 49 Long.toString(parseContentLengthFromRange(range)))); 50 51 } else if (originalRequest instanceof GetJobOutputRequest || originalRequest instanceof DescribeJobRequest) { 52 String resourcePath = mutableRequest.encodedPath(); 53 if (resourcePath != null) { 54 String newResourcePath = StringUtils.replace(resourcePath, "{jobType}", "archive-retrievals"); 55 mutableRequest.encodedPath(newResourcePath); 56 } 57 } 58 return mutableRequest; 59 } 60 parseContentLengthFromRange(String range)61 private long parseContentLengthFromRange(String range) { 62 if (range.startsWith("bytes=") || range.startsWith("bytes ")) { 63 range = range.substring(6); 64 } 65 66 String start = range.substring(0, range.indexOf('-')); 67 String end = range.substring(range.indexOf('-') + 1); 68 69 if (end.contains("/")) { 70 end = end.substring(0, end.indexOf('/')); 71 } 72 73 return Long.parseLong(end) - Long.parseLong(start) + 1; 74 } 75 76 } 77