Skip to content

Commit 7c05a6f

Browse files
committed
Allow generateParameterMap to optionally decode query params (for ALB requests)
1 parent 3ad7746 commit 7c05a6f

File tree

2 files changed

+60
-25
lines changed

2 files changed

+60
-25
lines changed

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

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ private void addPart(Map<String, List<Part>> params, String fieldName, Part newP
584584

585585
protected String[] getQueryParamValues(MultiValuedTreeMap<String, String> qs, String key, boolean isCaseSensitive) {
586586
List<String> value = getQueryParamValuesAsList(qs, key, isCaseSensitive);
587-
if (value == null){
587+
if (value == null) {
588588
return null;
589589
}
590590
return value.toArray(new String[0]);
@@ -607,39 +607,57 @@ protected List<String> getQueryParamValuesAsList(MultiValuedTreeMap<String, Stri
607607
}
608608

609609
protected Map<String, String[]> generateParameterMap(MultiValuedTreeMap<String, String> qs, ContainerConfig config) {
610+
return generateParameterMap(qs, config, false);
611+
}
612+
613+
protected Map<String, String[]> generateParameterMap(MultiValuedTreeMap<String, String> qs, ContainerConfig config, boolean decodeQueryParams) {
610614
Map<String, String[]> output;
611615

612616
Map<String, List<String>> formEncodedParams = getFormUrlEncodedParametersMap();
613617

614618
if (qs == null) {
615619
// Just transform the List<String> values to String[]
616-
output = formEncodedParams.entrySet().stream()
620+
return formEncodedParams.entrySet().stream()
617621
.collect(Collectors.toMap(Map.Entry::getKey, (e) -> e.getValue().toArray(new String[0])));
618-
} else {
619-
Map<String, List<String>> queryStringParams;
620-
if (config.isQueryStringCaseSensitive()) {
621-
queryStringParams = qs;
622-
} else {
623-
// If it's case insensitive, we check the entire map on every parameter
624-
queryStringParams = qs.entrySet().stream().parallel().collect(
625-
Collectors.toMap(
626-
Map.Entry::getKey,
627-
e -> getQueryParamValuesAsList(qs, e.getKey(), false)
628-
));
629-
}
630-
631-
// Merge formEncodedParams and queryStringParams Maps
632-
output = Stream.of(formEncodedParams, queryStringParams).flatMap(m -> m.entrySet().stream())
633-
.collect(
634-
Collectors.toMap(
635-
Map.Entry::getKey,
636-
e -> e.getValue().toArray(new String[0]),
637-
// If a parameter is in both Maps, we merge the list of values (and ultimately transform to String[])
638-
(formParam, queryParam) -> Stream.of(formParam, queryParam).flatMap(Stream::of).toArray(String[]::new)
639-
));
640-
641622
}
642623

624+
// decode all keys and values in map
625+
final MultiValuedTreeMap<String, String> decodedQs = new MultiValuedTreeMap<String, String>();
626+
if (decodeQueryParams) {
627+
for (Map.Entry<String, List<String>> entry : qs.entrySet()) {
628+
String k = decodeValueIfEncoded(entry.getKey());
629+
List<String> v = getQueryParamValuesAsList(qs, entry.getKey(), false).stream()
630+
.map(AwsHttpServletRequest::decodeValueIfEncoded)
631+
.collect(Collectors.toList());
632+
// addAll in case map has 2 keys that are identical once decoded
633+
decodedQs.addAll(k, v);
634+
}
635+
} else {
636+
decodedQs.putAll(qs);
637+
}
638+
639+
Map<String, List<String>> queryStringParams;
640+
if (config.isQueryStringCaseSensitive()) {
641+
queryStringParams = decodedQs;
642+
} else {
643+
// If it's case insensitive, we check the entire map on every parameter
644+
queryStringParams = decodedQs.entrySet().stream().collect(
645+
Collectors.toMap(
646+
Map.Entry::getKey,
647+
e -> getQueryParamValuesAsList(decodedQs, e.getKey(), false)
648+
));
649+
}
650+
651+
// Merge formEncodedParams and queryStringParams Maps
652+
output = Stream.of(formEncodedParams, queryStringParams).flatMap(m -> m.entrySet().stream())
653+
.collect(
654+
Collectors.toMap(
655+
Map.Entry::getKey,
656+
e -> e.getValue().toArray(new String[0]),
657+
// If a parameter is in both Maps, we merge the list of values (and ultimately transform to String[])
658+
(formParam, queryParam) -> Stream.of(formParam, queryParam).flatMap(Stream::of).toArray(String[]::new)
659+
));
660+
643661
return output;
644662
}
645663

aws-serverless-java-container-core/src/test/java/com/amazonaws/serverless/proxy/internal/servlet/AwsHttpServletRequestTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,23 @@ void parameterMapWithEncodedParams_generateParameterMap_validQuery() {
331331
assertTrue(paramMap.size() == 2);
332332
}
333333

334+
@Test
335+
void parameterMapWithEncodedParams_alb_generateParameterMap_validQuery() {
336+
AwsProxyHttpServletRequest request = new AwsProxyHttpServletRequest(encodedQueryStringAlb, mockContext, null, config);
337+
338+
Map<String, String[]> paramMap = null;
339+
try {
340+
paramMap = request.generateParameterMap(request.getAwsProxyRequest().getMultiValueQueryStringParameters(), config, true);
341+
} catch (Exception e) {
342+
e.printStackTrace();
343+
fail("Could not generate parameter map");
344+
}
345+
346+
assertArrayEquals(new String[]{"two"}, paramMap.get("one"));
347+
assertArrayEquals(new String[]{"{\"name\":\"faisal\"}"}, paramMap.get("json"));
348+
assertTrue(paramMap.size() == 2);
349+
}
350+
334351
@Test
335352
void parameterMapWithMultipleValues_generateParameterMap_validQuery() {
336353
AwsProxyHttpServletRequest request = new AwsProxyHttpServletRequest(multipleParams, mockContext, null, config);

0 commit comments

Comments
 (0)