-
Notifications
You must be signed in to change notification settings - Fork 571
Query parameter values not URL decoded when using a RequestStreamHandler implementation #1089
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
45df2b0
3ad7746
7c05a6f
916f2a2
f68e755
1109c8f
a202873
1785eb5
269a327
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -584,7 +584,7 @@ private void addPart(Map<String, List<Part>> params, String fieldName, Part newP | |
|
|
||
| protected String[] getQueryParamValues(MultiValuedTreeMap<String, String> qs, String key, boolean isCaseSensitive) { | ||
| List<String> value = getQueryParamValuesAsList(qs, key, isCaseSensitive); | ||
| if (value == null){ | ||
| if (value == null) { | ||
| return null; | ||
| } | ||
| return value.toArray(new String[0]); | ||
|
|
@@ -607,39 +607,57 @@ protected List<String> getQueryParamValuesAsList(MultiValuedTreeMap<String, Stri | |
| } | ||
|
|
||
| protected Map<String, String[]> generateParameterMap(MultiValuedTreeMap<String, String> qs, ContainerConfig config) { | ||
| return generateParameterMap(qs, config, false); | ||
| } | ||
|
|
||
| protected Map<String, String[]> generateParameterMap(MultiValuedTreeMap<String, String> qs, ContainerConfig config, boolean decodeQueryParams) { | ||
| Map<String, String[]> output; | ||
|
|
||
| Map<String, List<String>> formEncodedParams = getFormUrlEncodedParametersMap(); | ||
|
|
||
| if (qs == null) { | ||
| // Just transform the List<String> values to String[] | ||
| output = formEncodedParams.entrySet().stream() | ||
| return formEncodedParams.entrySet().stream() | ||
| .collect(Collectors.toMap(Map.Entry::getKey, (e) -> e.getValue().toArray(new String[0]))); | ||
| } else { | ||
| Map<String, List<String>> queryStringParams; | ||
| if (config.isQueryStringCaseSensitive()) { | ||
| queryStringParams = qs; | ||
| } else { | ||
| // If it's case insensitive, we check the entire map on every parameter | ||
| queryStringParams = qs.entrySet().stream().parallel().collect( | ||
| Collectors.toMap( | ||
| Map.Entry::getKey, | ||
| e -> getQueryParamValuesAsList(qs, e.getKey(), false) | ||
| )); | ||
| } | ||
|
|
||
| // Merge formEncodedParams and queryStringParams Maps | ||
| output = Stream.of(formEncodedParams, queryStringParams).flatMap(m -> m.entrySet().stream()) | ||
| .collect( | ||
| Collectors.toMap( | ||
| Map.Entry::getKey, | ||
| e -> e.getValue().toArray(new String[0]), | ||
| // If a parameter is in both Maps, we merge the list of values (and ultimately transform to String[]) | ||
| (formParam, queryParam) -> Stream.of(formParam, queryParam).flatMap(Stream::of).toArray(String[]::new) | ||
| )); | ||
|
|
||
| } | ||
|
|
||
| // decode all keys and values in map | ||
| final MultiValuedTreeMap<String, String> decodedQs = new MultiValuedTreeMap<String, String>(); | ||
| if (decodeQueryParams) { | ||
| for (Map.Entry<String, List<String>> entry : qs.entrySet()) { | ||
| String k = decodeValueIfEncoded(entry.getKey()); | ||
| List<String> v = getQueryParamValuesAsList(qs, entry.getKey(), false).stream() | ||
| .map(AwsHttpServletRequest::decodeValueIfEncoded) | ||
| .collect(Collectors.toList()); | ||
| // addAll in case map has 2 keys that are identical once decoded | ||
| decodedQs.addAll(k, v); | ||
| } | ||
| } else { | ||
| decodedQs.putAll(qs); | ||
| } | ||
|
|
||
| Map<String, List<String>> queryStringParams; | ||
| if (config.isQueryStringCaseSensitive()) { | ||
| queryStringParams = decodedQs; | ||
| } else { | ||
| // If it's case insensitive, we check the entire map on every parameter | ||
| queryStringParams = decodedQs.entrySet().stream().collect( | ||
|
||
| Collectors.toMap( | ||
| Map.Entry::getKey, | ||
| e -> getQueryParamValuesAsList(decodedQs, e.getKey(), false) | ||
| )); | ||
| } | ||
|
|
||
| // Merge formEncodedParams and queryStringParams Maps | ||
| output = Stream.of(formEncodedParams, queryStringParams).flatMap(m -> m.entrySet().stream()) | ||
| .collect( | ||
| Collectors.toMap( | ||
| Map.Entry::getKey, | ||
| e -> e.getValue().toArray(new String[0]), | ||
| // If a parameter is in both Maps, we merge the list of values (and ultimately transform to String[]) | ||
| (formParam, queryParam) -> Stream.of(formParam, queryParam).flatMap(Stream::of).toArray(String[]::new) | ||
| )); | ||
|
|
||
| return output; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -325,8 +325,17 @@ public String getContentType() { | |
|
|
||
| @Override | ||
| public String getParameter(String s) { | ||
|
|
||
| // decode key if ALB | ||
| if (request.getRequestSource() == RequestSource.ALB) { | ||
| s = decodeValueIfEncoded(s); | ||
| } | ||
|
|
||
| String queryStringParameter = getFirstQueryParamValue(request.getMultiValueQueryStringParameters(), s, config.isQueryStringCaseSensitive()); | ||
| if (queryStringParameter != null) { | ||
| if (request.getRequestSource() == RequestSource.ALB) { | ||
| queryStringParameter = decodeValueIfEncoded(queryStringParameter); | ||
| } | ||
| return queryStringParameter; | ||
| } | ||
|
|
||
|
|
@@ -345,15 +354,35 @@ public Enumeration<String> getParameterNames() { | |
| if (request.getMultiValueQueryStringParameters() == null) { | ||
| return Collections.enumeration(formParameterNames); | ||
| } | ||
| return Collections.enumeration(Stream.concat(formParameterNames.stream(), | ||
| request.getMultiValueQueryStringParameters().keySet().stream()).collect(Collectors.toSet())); | ||
|
|
||
| Set<String> paramNames = request.getMultiValueQueryStringParameters().keySet(); | ||
| if (request.getRequestSource() == RequestSource.ALB) { | ||
| paramNames = paramNames.stream().map(AwsProxyHttpServletRequest::decodeValueIfEncoded).collect(Collectors.toSet()); | ||
| } | ||
|
|
||
| return Collections.enumeration( | ||
| Stream.concat(formParameterNames.stream(), paramNames.stream()) | ||
| .collect(Collectors.toSet())); | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| @SuppressFBWarnings("PZLA_PREFER_ZERO_LENGTH_ARRAYS") // suppressing this as according to the specs we should be returning null here if we can't find params | ||
| public String[] getParameterValues(String s) { | ||
|
|
||
| // decode key if ALB | ||
| if (request.getRequestSource() == RequestSource.ALB) { | ||
| s = decodeValueIfEncoded(s); | ||
| } | ||
|
|
||
| // TODO lots of back and forth arrays and lists here, sort it out! | ||
| List<String> values = new ArrayList<>(Arrays.asList(getQueryParamValues(request.getMultiValueQueryStringParameters(), s, config.isQueryStringCaseSensitive()))); | ||
| // List<String> values = getQueryParamValuesAsList(request.getMultiValueQueryStringParameters(), s, config.isQueryStringCaseSensitive()); | ||
|
||
|
|
||
| // decode values if ALB | ||
| if (request.getRequestSource() == RequestSource.ALB) { | ||
| values = values.stream().map(AwsHttpServletRequest::decodeValueIfEncoded).collect(Collectors.toList()); | ||
| } | ||
|
|
||
| values.addAll(Arrays.asList(getFormBodyParameterCaseInsensitive(s))); | ||
|
|
||
|
|
@@ -367,7 +396,7 @@ public String[] getParameterValues(String s) { | |
|
|
||
| @Override | ||
| public Map<String, String[]> getParameterMap() { | ||
| return generateParameterMap(request.getMultiValueQueryStringParameters(), config); | ||
| return generateParameterMap(request.getMultiValueQueryStringParameters(), config, request.getRequestSource() == RequestSource.ALB); | ||
| } | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a fairly minor thing, but all this new code has a mix of spaces and tabs (first indentation is 4 spaces, then only tabs). Even though the project has some files with a mix of both, the vast majority of files are using spaces only. So try to keep this one with spaces only too. (The tests added are also using tabs, and hopefully you can change them to spaces)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😱 ... fixed, everything is spaces now