• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.core.internal.http.pipeline.stages;
17 
18 import static java.util.Collections.singletonList;
19 import static org.assertj.core.api.Assertions.assertThat;
20 import static org.assertj.core.api.Assertions.fail;
21 
22 import java.io.ByteArrayInputStream;
23 import java.net.URI;
24 import java.nio.charset.StandardCharsets;
25 import java.util.stream.Stream;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.junit.jupiter.api.Test;
28 import software.amazon.awssdk.core.Protocol;
29 import software.amazon.awssdk.core.SdkProtocolMetadata;
30 import software.amazon.awssdk.core.http.ExecutionContext;
31 import software.amazon.awssdk.core.http.NoopTestRequest;
32 import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
33 import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
34 import software.amazon.awssdk.core.internal.http.RequestExecutionContext;
35 import software.amazon.awssdk.http.ContentStreamProvider;
36 import software.amazon.awssdk.http.SdkHttpFullRequest;
37 import software.amazon.awssdk.http.SdkHttpMethod;
38 import software.amazon.awssdk.utils.IoUtils;
39 
40 public class QueryParametersToBodyStageTest {
41     public static final URI HTTP_LOCALHOST = URI.create("http://localhost:8080");
42     private QueryParametersToBodyStage stage;
43     private SdkHttpFullRequest.Builder requestBuilder;
44 
45     @BeforeEach
setup()46     public void setup() {
47         stage = new QueryParametersToBodyStage();
48         requestBuilder = SdkHttpFullRequest.builder()
49                                            .protocol(Protocol.HTTPS.toString())
50                                            .method(SdkHttpMethod.POST)
51                                            .putRawQueryParameter("key", singletonList("value"))
52                                            .uri(HTTP_LOCALHOST);
53     }
54 
verifyParametersMovedToBody(SdkHttpFullRequest output)55     private void verifyParametersMovedToBody(SdkHttpFullRequest output) throws Exception {
56         assertThat(output.rawQueryParameters()).hasSize(0);
57         assertThat(output.headers())
58             .containsKey("Content-Length")
59             .containsEntry("Content-Type", singletonList("application/x-www-form-urlencoded; charset=utf-8"));
60         assertThat(output.contentStreamProvider()).isNotEmpty();
61         String bodyContent = new String(IoUtils.toByteArray(output.contentStreamProvider().get().newStream()));
62         assertThat(bodyContent).isEqualTo("key=value");
63 
64     }
65 
verifyParametersUnaltered(SdkHttpFullRequest output, int numOfParams)66     private void verifyParametersUnaltered(SdkHttpFullRequest output, int numOfParams) {
67         assertThat(output.rawQueryParameters()).hasSize(numOfParams);
68         assertThat(output.headers()).isEmpty();
69     }
70 
71     @Test
postRequestWithNoBody_queryProtocol_parametersAreMovedToTheBody()72     public void postRequestWithNoBody_queryProtocol_parametersAreMovedToTheBody() throws Exception {
73         RequestExecutionContext requestExecutionContext = createRequestExecutionContext("query");
74         SdkHttpFullRequest output = stage.execute(requestBuilder, requestExecutionContext).build();
75 
76         verifyParametersMovedToBody(output);
77     }
78 
79     @Test
postRequestWithNoBody_ec2Protocol_parametersAreMovedToTheBody()80     public void postRequestWithNoBody_ec2Protocol_parametersAreMovedToTheBody() throws Exception {
81         RequestExecutionContext requestExecutionContext = createRequestExecutionContext("ec2");
82         SdkHttpFullRequest output = stage.execute(requestBuilder, requestExecutionContext).build();
83 
84         verifyParametersMovedToBody(output);
85     }
86 
87     @Test
postRequestWithNoBody_nonQueryProtocol_isUnaltered()88     public void postRequestWithNoBody_nonQueryProtocol_isUnaltered() throws Exception {
89         RequestExecutionContext requestExecutionContext = createRequestExecutionContext("json");
90         SdkHttpFullRequest output = stage.execute(requestBuilder, requestExecutionContext).build();
91 
92         int numOfParams = 1;
93         verifyParametersUnaltered(output, numOfParams);
94         assertThat(output.contentStreamProvider()).isEmpty();
95     }
96 
97     @Test
nonPostRequestsWithNoBodyAreUnaltered()98     public void nonPostRequestsWithNoBodyAreUnaltered() {
99         Stream.of(SdkHttpMethod.values())
100               .filter(m -> !m.equals(SdkHttpMethod.POST))
101               .forEach(method -> {
102                   try {
103                       nonPostRequestsUnaltered(method);
104                   } catch (Exception e) {
105                       fail("Exception thrown during stage execution");
106                   }
107               });
108     }
109 
110     @Test
postWithContentIsUnaltered()111     public void postWithContentIsUnaltered() throws Exception {
112         byte[] contentBytes = "hello".getBytes(StandardCharsets.UTF_8);
113         ContentStreamProvider contentProvider = () -> new ByteArrayInputStream(contentBytes);
114 
115         requestBuilder = requestBuilder.contentStreamProvider(contentProvider);
116         RequestExecutionContext requestExecutionContext = createRequestExecutionContext("query");
117         SdkHttpFullRequest output = stage.execute(requestBuilder, requestExecutionContext).build();
118 
119         int numOfParams = 1;
120         verifyParametersUnaltered(output, numOfParams);
121         assertThat(IoUtils.toByteArray(output.contentStreamProvider().get().newStream())).isEqualTo(contentBytes);
122     }
123 
124     @Test
onlyAlterRequestsIfParamsArePresent()125     public void onlyAlterRequestsIfParamsArePresent() throws Exception {
126         requestBuilder = requestBuilder.clearQueryParameters();
127         RequestExecutionContext requestExecutionContext = createRequestExecutionContext("query");
128         SdkHttpFullRequest output = stage.execute(requestBuilder, requestExecutionContext).build();
129 
130         int numOfParams = 0;
131         verifyParametersUnaltered(output, numOfParams);
132         assertThat(output.contentStreamProvider()).isEmpty();
133     }
134 
nonPostRequestsUnaltered(SdkHttpMethod method)135     private void nonPostRequestsUnaltered(SdkHttpMethod method) throws Exception {
136         requestBuilder = requestBuilder.method(method);
137         RequestExecutionContext requestExecutionContext = createRequestExecutionContext("query");
138         SdkHttpFullRequest output = stage.execute(requestBuilder, requestExecutionContext).build();
139 
140         int numOfParams = 1;
141         verifyParametersUnaltered(output, numOfParams);
142         assertThat(output.contentStreamProvider()).isEmpty();
143     }
144 
createRequestExecutionContext(String serviceProtocol)145     private RequestExecutionContext createRequestExecutionContext(String serviceProtocol) {
146         ExecutionAttributes executionAttributes = ExecutionAttributes.builder()
147                                                                      .put(SdkInternalExecutionAttribute.PROTOCOL_METADATA,
148                                                                           new TestProtocolMetadata(serviceProtocol))
149                                                                      .build();
150         ExecutionContext executionContext = ExecutionContext.builder()
151                                                             .executionAttributes(executionAttributes)
152                                                             .build();
153         return RequestExecutionContext.builder()
154                                       .originalRequest(NoopTestRequest.builder().build())
155                                       .executionContext(executionContext)
156                                       .build();
157     }
158 
159     private final class TestProtocolMetadata implements SdkProtocolMetadata {
160 
161         private String serviceProtocol;
162 
TestProtocolMetadata(String serviceProtocol)163         TestProtocolMetadata(String serviceProtocol) {
164             this.serviceProtocol = serviceProtocol;
165         }
166 
167         @Override
serviceProtocol()168         public String serviceProtocol() {
169             return serviceProtocol;
170         }
171     }
172 }
173