Skip to content

Commit c1c650f

Browse files
authored
Merge pull request #1386 from mbfreder/alb-encoding
fix: parameters encoding doesn't work for ALB when using Spring Cloud
2 parents 12b9e26 + 47279e1 commit c1c650f

File tree

3 files changed

+47
-13
lines changed

3 files changed

+47
-13
lines changed

aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/servlet/AwsHttpServletRequest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ protected String[] getQueryParamValues(MultiValuedTreeMap<String, String> qs, St
546546
return value.toArray(new String[0]);
547547
}
548548

549-
protected List<String> getQueryParamValuesAsList(MultiValuedTreeMap<String, String> qs, String key, boolean isCaseSensitive) {
549+
public static List<String> getQueryParamValuesAsList(MultiValuedTreeMap<String, String> qs, String key, boolean isCaseSensitive) {
550550
if (qs != null) {
551551
if (isCaseSensitive) {
552552
return qs.get(key);
@@ -788,7 +788,7 @@ static String cleanUri(String uri) {
788788
return finalUri;
789789
}
790790

791-
static String decodeValueIfEncoded(String value) {
791+
public static String decodeValueIfEncoded(String value) {
792792
if (value == null) {
793793
return null;
794794
}

aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringHttpProcessingUtils.java

+39-10
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
import java.nio.charset.Charset;
55
import java.nio.charset.StandardCharsets;
66
import java.util.Base64;
7+
import java.util.List;
78
import java.util.Map;
89
import java.util.Map.Entry;
910
import java.util.concurrent.CountDownLatch;
1011
import java.util.concurrent.TimeUnit;
11-
1212
import com.amazonaws.serverless.proxy.internal.HttpUtils;
13+
import com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletRequest;
14+
import com.amazonaws.serverless.proxy.model.RequestSource;
1315
import org.apache.commons.logging.Log;
1416
import org.apache.commons.logging.LogFactory;
1517
import org.springframework.cloud.function.serverless.web.ServerlessHttpServletRequest;
@@ -36,6 +38,9 @@
3638
import jakarta.servlet.ServletContext;
3739
import jakarta.servlet.http.HttpServletRequest;
3840

41+
import static com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletRequest.decodeValueIfEncoded;
42+
import static com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletRequest.getQueryParamValuesAsList;
43+
3944
class AwsSpringHttpProcessingUtils {
4045

4146
private static Log logger = LogFactory.getLog(AwsSpringHttpProcessingUtils.class);
@@ -116,13 +121,8 @@ private static HttpServletRequest generateRequest1(String request, Context lambd
116121

117122
ServerlessHttpServletRequest httpRequest = new ServerlessHttpServletRequest(servletContext, v1Request.getHttpMethod(), v1Request.getPath());
118123

119-
populateQueryStringParameters(v1Request.getQueryStringParameters(), httpRequest);
120-
if (v1Request.getMultiValueQueryStringParameters() != null) {
121-
MultiValueMapAdapter<String, String> queryStringParameters = new MultiValueMapAdapter(v1Request.getMultiValueQueryStringParameters());
122-
queryStringParameters.forEach((k, v) -> {
123-
httpRequest.setParameter(k, v.toArray(new String[0]));
124-
});
125-
}
124+
populateQueryStringParametersV1(v1Request, httpRequest);
125+
populateMultiValueQueryStringParametersV1(v1Request, httpRequest);
126126

127127
if (v1Request.getMultiValueHeaders() != null) {
128128
MultiValueMapAdapter headers = new MultiValueMapAdapter(v1Request.getMultiValueHeaders());
@@ -156,7 +156,7 @@ private static HttpServletRequest generateRequest2(String request, Context lambd
156156

157157
ServerlessHttpServletRequest httpRequest = new ServerlessHttpServletRequest(servletContext,
158158
v2Request.getRequestContext().getHttp().getMethod(), v2Request.getRequestContext().getHttp().getPath());
159-
populateQueryStringParameters(v2Request.getQueryStringParameters(), httpRequest);
159+
populateQueryStringParametersV2(v2Request.getQueryStringParameters(), httpRequest);
160160

161161
v2Request.getHeaders().forEach(httpRequest::setHeader);
162162

@@ -176,14 +176,43 @@ private static HttpServletRequest generateRequest2(String request, Context lambd
176176
return httpRequest;
177177
}
178178

179-
private static void populateQueryStringParameters(Map<String, String> requestParameters, ServerlessHttpServletRequest httpRequest) {
179+
private static void populateQueryStringParametersV2(Map<String, String> requestParameters, ServerlessHttpServletRequest httpRequest) {
180180
if (!CollectionUtils.isEmpty(requestParameters)) {
181181
for (Entry<String, String> entry : requestParameters.entrySet()) {
182182
// fix according to parseRawQueryString
183183
httpRequest.setParameter(entry.getKey(), entry.getValue());
184184
}
185185
}
186186
}
187+
188+
private static void populateQueryStringParametersV1(AwsProxyRequest v1Request, ServerlessHttpServletRequest httpRequest) {
189+
Map<String, String> requestParameters = v1Request.getQueryStringParameters();
190+
if (!CollectionUtils.isEmpty(requestParameters)) {
191+
// decode all keys and values in map
192+
for (Entry<String, String> entry : requestParameters.entrySet()) {
193+
String k = v1Request.getRequestSource() == RequestSource.ALB ? decodeValueIfEncoded(entry.getKey()) : entry.getKey();
194+
String v = v1Request.getRequestSource() == RequestSource.ALB ? decodeValueIfEncoded(entry.getValue()) : entry.getValue();
195+
httpRequest.setParameter(k, v);
196+
}
197+
}
198+
}
199+
200+
private static void populateMultiValueQueryStringParametersV1(AwsProxyRequest v1Request, ServerlessHttpServletRequest httpRequest) {
201+
if (v1Request.getMultiValueQueryStringParameters() != null) {
202+
MultiValueMapAdapter<String, String> queryStringParameters = new MultiValueMapAdapter<>(v1Request.getMultiValueQueryStringParameters());
203+
queryStringParameters.forEach((k, v) -> {
204+
String key = v1Request.getRequestSource() == RequestSource.ALB
205+
? decodeValueIfEncoded(k)
206+
: k;
207+
List<String> value = v1Request.getRequestSource() == RequestSource.ALB
208+
? getQueryParamValuesAsList(v1Request.getMultiValueQueryStringParameters(), k, false).stream()
209+
.map(AwsHttpServletRequest::decodeValueIfEncoded)
210+
.toList()
211+
: v;
212+
httpRequest.setParameter(key, value.toArray(new String[0]));
213+
});
214+
}
215+
}
187216

188217
private static <T> T readValue(String json, Class<T> clazz, ObjectMapper mapper) {
189218
try {

aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/AwsSpringHttpProcessingUtilsTests.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.Collection;
77

88
import com.amazonaws.serverless.proxy.RequestReader;
9+
import com.amazonaws.serverless.proxy.model.AlbContext;
910
import com.amazonaws.serverless.proxy.model.HttpApiV2ProxyRequest;
1011
import org.junit.jupiter.params.ParameterizedTest;
1112
import org.junit.jupiter.params.provider.MethodSource;
@@ -194,7 +195,7 @@ public class AwsSpringHttpProcessingUtilsTests {
194195
" },\n" +
195196
" \"httpMethod\": \"POST\",\n" +
196197
" \"path\": \"/async\",\n" +
197-
" \"multiValueQueryStringParameters\": { \"parameter1\": [\"value1\", \"value2\"]},\n" +
198+
" \"multiValueQueryStringParameters\": { \"parameter1\": [\"value1\", \"value2\"], \"parameter2\": [\"1970-01-01T00%3A00%3A00.004Z\"]},\n" +
198199
" \"multiValueHeaders\": {\n" +
199200
" \"accept\": [\"text/html,application/xhtml+xml\"],\n" +
200201
" \"accept-language\": [\"en-US,en;q=0.8\"],\n" +
@@ -238,6 +239,10 @@ private static void assertRequest(HttpServletRequest request) {
238239
assertEquals("value1", request.getParameter("parameter1"));
239240
assertArrayEquals(new String[]{"value1", "value2"}, request.getParameterValues("parameter1"));
240241
}
242+
if (request.getAttribute(RequestReader.ALB_CONTEXT_PROPERTY) instanceof AlbContext) {
243+
// query params should be decoded
244+
assertEquals("1970-01-01T00:00:00.004Z", request.getParameter("parameter2"));
245+
}
241246
}
242247

243248
@MethodSource("data")

0 commit comments

Comments
 (0)