Skip to content

Commit 722f187

Browse files
authored
Fix for Signing Error when ampersand character included in HttpQuery when using DefaultAwsCrtV4aSigner (#4800)
* Fix for Signing Error when ampersand character included in HttpQuery when using DefaultAwsCrtV4aSigner
1 parent e995106 commit 722f187

File tree

3 files changed

+105
-3
lines changed

3 files changed

+105
-3
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "bugfix",
3+
"category": "AWS SDK for Java v2",
4+
"contributor": "",
5+
"description": "Fix for Signing Error when ampersand character included in HttpQuery when using DefaultAwsCrtV4aSigner."
6+
}

core/auth-crt/src/main/java/software/amazon/awssdk/authcrt/signer/internal/CrtHttpRequestConverter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package software.amazon.awssdk.authcrt.signer.internal;
1717

1818
import static java.lang.Math.min;
19+
import static software.amazon.awssdk.utils.http.SdkHttpUtils.urlDecode;
1920

2021
import java.io.ByteArrayInputStream;
2122
import java.io.IOException;
@@ -82,7 +83,7 @@ public SdkHttpFullRequest crtRequestToHttp(SdkHttpFullRequest inputRequest, Http
8283
}
8384

8485
builder.encodedPath(fullUri.getRawPath());
85-
String remainingQuery = fullUri.getQuery();
86+
String remainingQuery = fullUri.getRawQuery();
8687

8788
builder.clearQueryParameters();
8889
while (remainingQuery != null && remainingQuery.length() > 0) {
@@ -95,14 +96,14 @@ public SdkHttpFullRequest crtRequestToHttp(SdkHttpFullRequest inputRequest, Http
9596
queryValue = remainingQuery.substring(nextAssign + 1, nextQuery);
9697
}
9798

98-
builder.appendRawQueryParameter(queryName, queryValue);
99+
builder.appendRawQueryParameter(urlDecode(queryName), urlDecode(queryValue));
99100
} else {
100101
String queryName = remainingQuery;
101102
if (nextQuery >= 0) {
102103
queryName = remainingQuery.substring(0, nextQuery);
103104
}
104105

105-
builder.appendRawQueryParameter(queryName, null);
106+
builder.appendRawQueryParameter(urlDecode(queryName), null);
106107
}
107108

108109
if (nextQuery >= 0) {

core/auth-crt/src/test/java/software/amazon/awssdk/authcrt/signer/internal/CrtHttpRequestConverterTest.java

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
import java.util.List;
2626
import org.junit.jupiter.api.BeforeEach;
2727
import org.junit.jupiter.api.Test;
28+
import org.junit.jupiter.params.ParameterizedTest;
29+
import org.junit.jupiter.params.provider.Arguments;
30+
import org.junit.jupiter.params.provider.MethodSource;
2831
import software.amazon.awssdk.crt.http.HttpHeader;
2932
import software.amazon.awssdk.crt.http.HttpRequest;
3033
import software.amazon.awssdk.crt.http.HttpRequestBodyStream;
@@ -71,6 +74,49 @@ public void request_withHeaders_isConvertedToCrtFormat() {
7174
assertHttpRequestSame(request, crtHttpRequest);
7275
}
7376

77+
public static List<Arguments> specialCharactersEncoding() {
78+
return Arrays.asList(
79+
Arguments.of("hello world", "hello%20world"),
80+
Arguments.of("apple & orange", "apple%20%26%20orange"),
81+
Arguments.of("/path/to/resource", "%2Fpath%2Fto%2Fresource"),
82+
Arguments.of("search?q=term", "search%3Fq%3Dterm"),
83+
Arguments.of("key=value", "key%3Dvalue"),
84+
Arguments.of("section#1", "section%231"),
85+
Arguments.of("one+two", "one%2Btwo"),
86+
Arguments.of("[email protected]", "user%40domain.com"),
87+
Arguments.of("protocol:8080", "protocol%3A8080"),
88+
Arguments.of("item1;item2", "item1%3Bitem2"),
89+
Arguments.of("apple,orange", "apple%2Corange"),
90+
Arguments.of("quoted text", "quoted%20text"),
91+
Arguments.of("don't", "don%27t"),
92+
Arguments.of("20% discount", "20%25%20discount"),
93+
Arguments.of("important!", "important%21"),
94+
Arguments.of("(example)", "%28example%29"),
95+
Arguments.of("items[1]", "items%5B1%5D"),
96+
Arguments.of("{key: 'value'}", "%7Bkey%3A%20%27value%27%7D"),
97+
Arguments.of("first line\nsecond line", "first%20line%0Asecond%20line"),
98+
Arguments.of("before\rafter", "before%0Dafter"),
99+
Arguments.of("left\tcenter\tright", "left%09center%09right")
100+
);
101+
}
102+
103+
@ParameterizedTest(name = "{index} {0}")
104+
@MethodSource("specialCharactersEncoding")
105+
public void request_withSpecialCharactersQueryParams_isConvertedToCrtFormat(String rawParameters, String encodedParameters) {
106+
SdkHttpFullRequest request = SdkHttpFullRequest.builder()
107+
.method(SdkHttpMethod.GET)
108+
.putRawQueryParameter("headerOne", rawParameters)
109+
.putHeader("Host", "demo.us-east-1.amazonaws.com")
110+
.encodedPath("/path")
111+
.uri(URI.create("https://demo.us-east-1.amazonaws.com"))
112+
.build();
113+
HttpRequest crtHttpRequest = converter.requestToCrt(request);
114+
assertThat(crtHttpRequest.getMethod()).isEqualTo("GET");
115+
assertThat(crtHttpRequest.getEncodedPath()).isEqualTo(String.format("/path?headerOne=%s", encodedParameters));
116+
assertHttpRequestSame(request, crtHttpRequest);
117+
}
118+
119+
74120
@Test
75121
public void request_withQueryParams_isConvertedToCrtFormat() {
76122
SdkHttpFullRequest request = SdkHttpFullRequest.builder()
@@ -87,6 +133,55 @@ public void request_withQueryParams_isConvertedToCrtFormat() {
87133
assertHttpRequestSame(request, crtHttpRequest);
88134
}
89135

136+
137+
@Test
138+
public void request_withQueryParams_WithAmpersandAndEqualsInKeyAndValue_isConvertedToCrtFormat() {
139+
SdkHttpFullRequest request = SdkHttpFullRequest.builder()
140+
.method(SdkHttpMethod.GET)
141+
.putRawQueryParameter("ampersand&", "one & two")
142+
.putRawQueryParameter("equals=", "three = three")
143+
.putHeader("Host", "demo.us-east-1.amazonaws.com")
144+
.encodedPath("/path")
145+
.uri(URI.create("https://demo.us-east-1.amazonaws.com"))
146+
.build();
147+
HttpRequest crtHttpRequest = converter.requestToCrt(request);
148+
assertThat(crtHttpRequest.getMethod()).isEqualTo("GET");
149+
assertThat(crtHttpRequest.getEncodedPath()).isEqualTo("/path?ampersand%26=one%20%26%20two&equals%3D=three%20%3D%20three");
150+
assertHttpRequestSame(request, crtHttpRequest);
151+
}
152+
153+
@Test
154+
public void request_withQueryParams_AmpersandAndEqualsInValue_isConvertedToCrtFormat() {
155+
SdkHttpFullRequest request = SdkHttpFullRequest.builder()
156+
.method(SdkHttpMethod.GET)
157+
.putRawQueryParameter("ampersand", "one & two")
158+
.putRawQueryParameter("equals", "three = three")
159+
.putHeader("Host", "demo.us-east-1.amazonaws.com")
160+
.encodedPath("/path")
161+
.uri(URI.create("https://demo.us-east-1.amazonaws.com"))
162+
.build();
163+
HttpRequest crtHttpRequest = converter.requestToCrt(request);
164+
assertThat(crtHttpRequest.getMethod()).isEqualTo("GET");
165+
assertThat(crtHttpRequest.getEncodedPath()).isEqualTo("/path?ampersand=one%20%26%20two&equals=three%20%3D%20three");
166+
assertHttpRequestSame(request, crtHttpRequest);
167+
}
168+
169+
@Test
170+
public void request_withQueryParams_EmptyApersandAndEqualsInValue_isConvertedToCrtFormat() {
171+
SdkHttpFullRequest request = SdkHttpFullRequest.builder()
172+
.method(SdkHttpMethod.GET)
173+
.putRawQueryParameter("&ampersand&", "")
174+
.putRawQueryParameter("=equals=", "")
175+
.putHeader("Host", "demo.us-east-1.amazonaws.com")
176+
.encodedPath("/path")
177+
.uri(URI.create("https://demo.us-east-1.amazonaws.com"))
178+
.build();
179+
HttpRequest crtHttpRequest = converter.requestToCrt(request);
180+
assertThat(crtHttpRequest.getMethod()).isEqualTo("GET");
181+
assertThat(crtHttpRequest.getEncodedPath()).isEqualTo("/path?%26ampersand%26=&%3Dequals%3D=");
182+
assertHttpRequestSame(request, crtHttpRequest);
183+
}
184+
90185
@Test
91186
public void request_withEmptyPath_isConvertedToCrtFormat() {
92187
SdkHttpFullRequest request = SdkHttpFullRequest.builder()

0 commit comments

Comments
 (0)