Skip to content
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

AwsHttpApiV2ProxyHttpServletRequest.getParameterMap returns arrays containing null for empty query params #427

Closed
bogdanb opened this issue Sep 17, 2021 · 4 comments
Assignees
Labels

Comments

@bogdanb
Copy link

bogdanb commented Sep 17, 2021

To help us debug your issue fill in the basic information below using the options provided

Serverless Java Container version: 1.6

Implementations: Spring Boot 2

Framework version: eg SpringBoot 2.5.3

Frontend service: REST API / HTTP API / ALB

Deployment method: Console

Scenario

I’m using a SpringBootLambdaContainerHandler<HttpApiV2ProxyRequest, AwsProxyResponse> to run a (pre-existing) Spring Boot application in AWS Lambda. The app receives pretty simple REST requests (via CloudFront). For example, a snippet of an event received looks like this:

{
    "version": "2.0",
    "routeKey": "$default",
    "rawPath": "/rest/[...snip...]",
    "rawQueryString": "query=&maxResults=20",
    "queryStringParameters": {
        "maxResults": "20",
        "query": ""
    },
    [...snip...]
}

Expected behavior

I expected the existing app to work more-or-less as it does outside Lambda, when it receives the REST requests directly.

Actual behavior

In practice, I got a crash, in library code outside my control. I think it’s caused by a bug in aws-sjc. What happens is that for the request above, AwsHttpApiV2ProxyHttpServletRequest.getParameterMap returns a HashMap which looks kind of like this:

  {maxResults=[20], query=[null]}

To be precise, the value for the query parameter is a String[] array that contains a single null value.

The crash happens because the code that consumes the parameter map assumes that the array values will not contain null. My understanding is that it should not (instead, the array should have contained an empty string), and the JavaDoc of the ServletRequest.getParameterMap method seems to agree:

Returns: an immutable java.util.Map containing parameter names as keys and parameter values as map values. The keys in the parameter map are of type String. The values in the parameter map are of type String array.

AwsHttpApiV2ProxyHttpServletRequest seems to be doubly-wrong: First, because it returns null in the query array, instead of an empty string. Second (and maybe less importantly), because the returned Map is not immutable.

Steps to reproduce

Include something like this in any Spring Boot application, use SpringBootProxyHandlerBuilder to pass requests from CloudFront to it, and try any request that contains a query parameter with the empty value:

@Component @Order(Ordered.HIGHEST_PRECEDENCE) @Slf4j
public class ParametersDebuggingFilter extends OncePerRequestFilter
{
    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
        final FilterChain filterChain) throws ServletException, IOException
    {
        log.debug("Request parameter map: {} (class: {}, req: {})",
            Maps.transformValues(request.getParameterMap(),
                array -> array == null ? null : "%s@%d".formatted(Arrays.asList(array), array.length)),
            request.getParameterMap().getClass(), request.getClass());

        filterChain.doFilter(request, response);
    }
}

Full log output

For the above request, the output in my case looks like this:

Request parameter map: {maxResults=[20]@1, query=[null]@1} (class: class java.util.HashMap, req: class com.amazonaws.serverless.proxy.internal.servlet.AwsHttpApiV2ProxyHttpServletRequest)
@deki
Copy link
Collaborator

deki commented Dec 27, 2021

Hi @bogdanb,
I'm sorry that no one responded so far. Would you be willing create a pull request with a proposed fix for this issue?

@deki deki added the bug label Jan 3, 2022
@deki deki self-assigned this Mar 30, 2022
@deki
Copy link
Collaborator

deki commented Mar 30, 2022

This was introduced by a fix for #363. Will provide a fix for the next release. Let me know if it works for you.

deki added a commit that referenced this issue Mar 30, 2022
deki added a commit to deki/aws-serverless-java-container that referenced this issue Mar 30, 2022
@deki deki closed this as completed Mar 30, 2022
@bogdanb
Copy link
Author

bogdanb commented Mar 30, 2022

@deki Thanks, Dennis! How can tell when the next release happens so I can test it there? Is there somewhere I can subscribe or something?

@deki
Copy link
Collaborator

deki commented Mar 30, 2022

It's included in the 1.8 release which is already available on Maven Central.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants