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.s3.internal.handlers;
17
18 import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely;
19
20 import java.io.InputStream;
21 import java.nio.ByteBuffer;
22 import java.util.Optional;
23 import java.util.function.Predicate;
24 import org.reactivestreams.Publisher;
25 import software.amazon.awssdk.annotations.SdkInternalApi;
26 import software.amazon.awssdk.core.interceptor.Context;
27 import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
28 import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
29 import software.amazon.awssdk.core.internal.async.SdkPublishers;
30 import software.amazon.awssdk.http.AbortableInputStream;
31 import software.amazon.awssdk.services.s3.model.GetBucketPolicyRequest;
32 import software.amazon.awssdk.utils.IoUtils;
33 import software.amazon.awssdk.utils.StringInputStream;
34
35 /**
36  * GetBucketPolicy returns just JSON so we wrap in XML so that it is unmarshalled correctly.
37  */

38 @SdkInternalApi
39 public final class GetBucketPolicyInterceptor implements ExecutionInterceptor {
40     private static final String XML_ENVELOPE_PREFIX = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Policy><![CDATA[";
41     private static final String XML_ENVELOPE_SUFFIX = "]]></Policy>";
42
43     private static final Predicate<Context.ModifyHttpResponse> INTERCEPTOR_CONTEXT_PREDICATE =
44         context -> context.request() instanceof GetBucketPolicyRequest && context.httpResponse().isSuccessful();
45
46     @Override
47     public Optional<InputStream> modifyHttpResponseContent(Context.ModifyHttpResponse context,
48                                                            ExecutionAttributes executionAttributes) {
49         if (INTERCEPTOR_CONTEXT_PREDICATE.test(context)) {
50
51             String policy = context.responseBody()
52                                    .map(r -> invokeSafely(() -> IoUtils.toUtf8String(r)))
53                                    .orElse(null);
54
55             if (policy != null) {
56                 String xml = XML_ENVELOPE_PREFIX + policy + XML_ENVELOPE_SUFFIX;
57                 return Optional.of(AbortableInputStream.create(new StringInputStream(xml)));
58             }
59         }
60
61         return context.responseBody();
62     }
63
64     @Override
65     public Optional<Publisher<ByteBuffer>> modifyAsyncHttpResponseContent(Context.ModifyHttpResponse context,
66                                                                           ExecutionAttributes executionAttributes) {
67         if (INTERCEPTOR_CONTEXT_PREDICATE.test(context)) {
68             return context.responsePublisher().map(
69                 body -> SdkPublishers.envelopeWrappedPublisher(body, XML_ENVELOPE_PREFIX, XML_ENVELOPE_SUFFIX));
70         }
71
72         return context.responsePublisher();
73     }
74 }
75