Skip to content

Commit ee31237

Browse files
authored
Fixed the issue where slash from path parameter got removed with endp… (#3964)
* Fixed the issue where slash from path parameter got removed with endpoint override that contains a trailing slash * Not strip slash
1 parent 1a23009 commit ee31237

File tree

3 files changed

+52
-8
lines changed

3 files changed

+52
-8
lines changed

codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AwsEndpointProviderUtils.java.resource

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,19 +150,33 @@ public final class AwsEndpointProviderUtils {
150150
String clientEndpointPath = clientEndpoint.getRawPath();
151151

152152
// [client endpoint path]/[request path]
153-
String requestPath = request.getUri().getRawPath();
153+
String requestPath = request.encodedPath();
154154

155155
// [client endpoint path]/[additional path added by resolver]
156156
String resolvedUriPath = resolvedUri.getRawPath();
157157

158-
// our goal is to construct [client endpoint path]/[additional path added by resolver]/[request path], so we
159-
// just need to strip the client endpoint path from the marshalled request path to isolate just the part added
160-
// by the marshaller
161-
String requestPathWithClientPathRemoved = StringUtils.replaceOnce(requestPath, clientEndpointPath, "");
162-
String finalPath = SdkHttpUtils.appendUri(resolvedUriPath, requestPathWithClientPathRemoved);
158+
String finalPath = requestPath;
159+
160+
// If there is an additional path added by resolver, i.e., [additional path added by resolver] not null,
161+
// we need to combine the path
162+
if (!resolvedUriPath.equals(clientEndpointPath)) {
163+
finalPath = combinePath(clientEndpointPath, requestPath, resolvedUriPath);
164+
}
163165

164166
return request.toBuilder().protocol(resolvedUri.getScheme()).host(resolvedUri.getHost()).port(resolvedUri.getPort())
165-
.encodedPath(finalPath).build();
167+
.encodedPath(finalPath).build();
168+
}
169+
170+
/**
171+
* Our goal is to construct [client endpoint path]/[additional path added by resolver]/[request path], so we just need to
172+
* strip the client endpoint path from the marshalled request path to isolate just the part added by the marshaller. Trailing
173+
* slash is removed from client endpoint path before stripping because it could cause the leading slash to be removed from the
174+
* request path: e.g., StringUtils.replaceOnce("/", "//test", "") generates "/test" and the expected result is "//test"
175+
*/
176+
private static String combinePath(String clientEndpointPath, String requestPath, String resolvedUriPath) {
177+
String requestPathWithClientPathRemoved = StringUtils.replaceOnce(requestPath, clientEndpointPath, "");
178+
String finalPath = SdkHttpUtils.appendUri(resolvedUriPath, requestPathWithClientPathRemoved);
179+
return finalPath;
166180
}
167181

168182
public static AwsRequest addHeaders(AwsRequest request, Map<String, List<String>> headers) {

core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkExecutionAttribute.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ public class SdkExecutionAttribute {
6767
public static final ExecutionAttribute<Boolean> ENDPOINT_OVERRIDDEN = new ExecutionAttribute<>("EndpointOverridden");
6868

6969
/**
70-
* This is the endpointOverride (if {@link #ENDPOINT_OVERRIDDEN} is true), otherwise null.
70+
* This is the endpointOverride (if {@link #ENDPOINT_OVERRIDDEN} is true), otherwise the endpoint generated from regional
71+
* metadata.
7172
*/
7273
public static final ExecutionAttribute<URI> CLIENT_ENDPOINT = new ExecutionAttribute<>("EndpointOverride");
7374

test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/AwsEndpointProviderUtilsTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,35 @@ public void setUri_combinesPathsCorrectly() {
250250
.isEqualTo("https://override.example.com/a/b/c");
251251
}
252252

253+
@Test
254+
public void setUri_doubleSlash_combinesPathsCorrectly() {
255+
URI clientEndpoint = URI.create("https://override.example.com/a");
256+
URI requestUri = URI.create("https://override.example.com/a//c");
257+
URI resolvedUri = URI.create("https://override.example.com/a/b");
258+
259+
SdkHttpRequest request = SdkHttpRequest.builder()
260+
.uri(requestUri)
261+
.method(SdkHttpMethod.GET)
262+
.build();
263+
264+
assertThat(AwsEndpointProviderUtils.setUri(request, clientEndpoint, resolvedUri).getUri().toString())
265+
.isEqualTo("https://override.example.com/a/b//c");
266+
}
267+
268+
@Test
269+
public void setUri_withTrailingSlashNoPath_combinesPathsCorrectly() {
270+
URI clientEndpoint = URI.create("https://override.example.com/");
271+
URI requestUri = URI.create("https://override.example.com//a");
272+
URI resolvedUri = URI.create("https://override.example.com/");
273+
SdkHttpRequest request = SdkHttpRequest.builder()
274+
.uri(requestUri)
275+
.method(SdkHttpMethod.GET)
276+
.build();
277+
278+
assertThat(AwsEndpointProviderUtils.setUri(request, clientEndpoint, resolvedUri).getUri().toString())
279+
.isEqualTo("https://override.example.com//a");
280+
}
281+
253282
@Test
254283
public void setHeaders_existingValuesOnOverride_combinesWithNewValues() {
255284
AwsRequest request = AllTypesRequest.builder()

0 commit comments

Comments
 (0)