Skip to content

Commit cc97689

Browse files
authored
Remove Bucket param from S3 request URIs (#3446)
In E2.0, the rule set handles adding the Bucket to the request URI so we remove it from the model to prevent the marshallers from adding it to the path.
1 parent cd7358a commit cc97689

File tree

4 files changed

+153
-43
lines changed

4 files changed

+153
-43
lines changed

codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/DefaultCustomizationProcessor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public static CodegenCustomizationProcessor getProcessorFor(
3535
new OperationModifiersProcessor(config.getOperationModifiers()),
3636
new RemoveExceptionMessagePropertyProcessor(),
3737
new UseLegacyEventGenerationSchemeProcessor(),
38-
new NewAndLegacyEventStreamProcessor()
39-
);
38+
new NewAndLegacyEventStreamProcessor(),
39+
new S3RemoveBucketFromUriProcessor()
40+
);
4041
}
4142
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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.codegen.customization.processors;
17+
18+
import org.slf4j.Logger;
19+
import org.slf4j.LoggerFactory;
20+
import software.amazon.awssdk.codegen.customization.CodegenCustomizationProcessor;
21+
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
22+
import software.amazon.awssdk.codegen.model.service.Operation;
23+
import software.amazon.awssdk.codegen.model.service.ServiceModel;
24+
import software.amazon.awssdk.utils.StringUtils;
25+
26+
/**
27+
* With Endpoints 2.0, the endpoint rule set for S3 is responsible for taking the {@code Bucket} parameter from the input and
28+
* adding it to the request URI. To make this work, we preprocess the model to remove it from the HTTP definition so that the
29+
* marshallers don't add it to the path as well.
30+
*/
31+
public class S3RemoveBucketFromUriProcessor implements CodegenCustomizationProcessor {
32+
private static final Logger log = LoggerFactory.getLogger(S3RemoveBucketFromUriProcessor.class);
33+
34+
@Override
35+
public void preprocess(ServiceModel serviceModel) {
36+
if (!isS3(serviceModel)) {
37+
return;
38+
}
39+
40+
log.info("Preprocessing S3 model to remove {Bucket} from request URIs");
41+
42+
serviceModel.getOperations().forEach(this::removeBucketFromUriIfNecessary);
43+
}
44+
45+
@Override
46+
public void postprocess(IntermediateModel intermediateModel) {
47+
// no-op
48+
}
49+
50+
private boolean isS3(ServiceModel serviceModel) {
51+
return "S3".equals(serviceModel.getMetadata().getServiceId());
52+
}
53+
54+
private void removeBucketFromUriIfNecessary(String opName, Operation operation) {
55+
String requestUri = operation.getHttp().getRequestUri();
56+
String newUri = StringUtils.replaceOnce(requestUri, "/{Bucket}", "");
57+
58+
log.info("{}: replacing existing request URI '{}' with '{}", opName, requestUri, newUri);
59+
60+
operation.getHttp().setRequestUri(newUri);
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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.codegen.customization.processors;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
import java.util.HashMap;
21+
import java.util.Map;
22+
import org.junit.Test;
23+
import software.amazon.awssdk.codegen.model.service.Http;
24+
import software.amazon.awssdk.codegen.model.service.Operation;
25+
import software.amazon.awssdk.codegen.model.service.ServiceMetadata;
26+
import software.amazon.awssdk.codegen.model.service.ServiceModel;
27+
28+
public class S3RemoveBucketFromUriProcessorTest {
29+
private static final String WITH_BUCKET_URI_OPERATION = "WithBucketInUri";
30+
private static final String WITHOUT_BUCKET_URI_OPERATION = "WithoutBucketInUri";
31+
private static final String WITH_BUCKET_URI = "/{Bucket}/{Key+}";
32+
private static final String WITHOUT_BUCKET_URI = "/{Key+}";
33+
34+
private final S3RemoveBucketFromUriProcessor processor = new S3RemoveBucketFromUriProcessor();
35+
36+
@Test
37+
public void preprocess_serviceNotS3_doesNotModifyUri() {
38+
ServiceModel nonS3 = createServiceModel("NonS3");
39+
processor.preprocess(nonS3);
40+
41+
Map<String, Operation> operations = nonS3.getOperations();
42+
43+
assertThat(operations.get(WITH_BUCKET_URI_OPERATION).getHttp().getRequestUri()).isEqualTo(WITH_BUCKET_URI);
44+
assertThat(operations.get(WITHOUT_BUCKET_URI_OPERATION).getHttp().getRequestUri()).isEqualTo(WITHOUT_BUCKET_URI);
45+
}
46+
47+
@Test
48+
public void preprocess_serviceIsS3_operationHasBucket_modifiesUri() {
49+
ServiceModel s3 = createServiceModel("S3");
50+
processor.preprocess(s3);
51+
52+
Map<String, Operation> operations = s3.getOperations();
53+
54+
assertThat(operations.get(WITH_BUCKET_URI_OPERATION).getHttp().getRequestUri()).isEqualTo("/{Key+}");
55+
}
56+
57+
@Test
58+
public void preprocess_serviceIsS3_operationDoesNotHaveBucket_noModification() {
59+
ServiceModel s3 = createServiceModel("S3");
60+
processor.preprocess(s3);
61+
62+
Map<String, Operation> operations = s3.getOperations();
63+
64+
assertThat(operations.get(WITHOUT_BUCKET_URI_OPERATION).getHttp().getRequestUri()).isEqualTo(WITHOUT_BUCKET_URI);
65+
}
66+
67+
private static ServiceModel createServiceModel(String serviceId) {
68+
ServiceModel model = new ServiceModel();
69+
70+
ServiceMetadata serviceMetadata = new ServiceMetadata();
71+
serviceMetadata.setServiceId(serviceId);
72+
model.setMetadata(serviceMetadata);
73+
74+
Operation operationWithBucketInUri = new Operation()
75+
.withHttp(new Http().withRequestUri(WITH_BUCKET_URI));
76+
77+
Operation operationWithoutBucketInUri = new Operation()
78+
.withHttp(new Http().withRequestUri(WITHOUT_BUCKET_URI));
79+
80+
Map<String, Operation> operations = new HashMap<>();
81+
operations.put(WITH_BUCKET_URI_OPERATION, operationWithBucketInUri);
82+
operations.put(WITHOUT_BUCKET_URI_OPERATION, operationWithoutBucketInUri);
83+
84+
model.setOperations(operations);
85+
86+
return model;
87+
}
88+
}

services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/RemoveBucketFromPathInterceptor.java

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)