Repository: awslabs/aws-lambda-rust-runtime (language: rust)

Issue:
`lambda_http::Request` should expose a `QueryMap` from a `raw_query_string`
This is a follow-up to [this issue](https://github.com/calavera/query-map-rs/issues/1)  @calavera 

I had a new idea while reading closely the [Payload format Version 2.0](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format). There is a `rawQueryString` field! This means we can use this field to correctly parse query parameters into a QueryMap.

The lambda_http crate already appends this  `raw_query_string` into the `Uri` of the request (as seen in the function `request::into_api_gateway_v2_request`), and the 
wrong
 `QueryStringParameters` are put inside an extension of the request.

So my idea is... maybe we can also expose the`raw_query_string` in some way but already parsed into a `QueryMap`. Something like an extension that can be accessed through the `RequestExt` trait. My reasoning is that most people using API Gateway expect the `QueryStringParameters` to behave according to the [whatwg spec](https://url.spec.whatwg.org/#urlencoded-parsing).

Maybe we can put a warning about this weird quirk of AWS in the documentation of `RequestExt::query_string_parameters` and push devs to use a new method like `raw_query_string`.


Discussion / hints:
what if we make the `QueryStringParameters` use the right parameters by creating a QueryMap from the `raw_query_string`, instead of the mangled apigw v2 ones? To be honest, I don't believe anyone would expect the current behavior of not parsing commas correctly.
That is much better in my opinion. The reason I didn't propose that is that technically the official behavior is to split at commas, but yes... no one expects that.

We should put a note in the documentation saying that we are not following the API Gateway Payload format Version 2.0 on purpose.
yeah, if someone needs the payload format version 2 behavior, they can use the raw runtime and receive those events specifically, they don't need to use lambda_http.

Fix patch:
diff --git a/lambda-http/src/request.rs b/lambda-http/src/request.rs
index 9c9d84db..d4770dd6 100644
--- a/lambda-http/src/request.rs
+++ b/lambda-http/src/request.rs
@@ -63,6 +63,17 @@ fn into_api_gateway_v2_request(ag: ApiGatewayV2httpRequest) -> http::Request<Bod
     let http_method = ag.request_context.http.method.clone();
     let raw_path = ag.raw_path.unwrap_or_default();
 
+    // don't use the query_string_parameters from API GW v2 to
+    // populate the QueryStringParameters extension because
+    // the value is not compatible with the whatgw specification.
+    // See: https://github.com/awslabs/aws-lambda-rust-runtime/issues/470
+    // See: https://url.spec.whatwg.org/#urlencoded-parsing
+    let query_string_parameters = if let Some(query) = &ag.raw_query_string {
+        query.parse().unwrap() // this is Infallible
+    } else {
+        ag.query_string_parameters
+    };
+
     let builder = http::Request::builder()
         .uri({
             let scheme = ag
@@ -87,7 +98,7 @@ fn into_api_gateway_v2_request(ag: ApiGatewayV2httpRequest) -> http::Request<Bod
             url
         })
         .extension(RawHttpPath(raw_path))
-        .extension(QueryStringParameters(ag.query_string_parameters))
+        .extension(QueryStringParameters(query_string_parameters))
         .extension(PathParameters(QueryMap::from(ag.path_parameters)))
         .extension(StageVariables(QueryMap::from(ag.stage_variables)))
         .extension(RequestContext::ApiGatewayV2(ag.request_context));


Test patch: