44import  java .nio .charset .Charset ;
55import  java .nio .charset .StandardCharsets ;
66import  java .util .Base64 ;
7+ import  java .util .List ;
78import  java .util .Map ;
89import  java .util .Map .Entry ;
910import  java .util .concurrent .CountDownLatch ;
1011import  java .util .concurrent .TimeUnit ;
11- 
1212import  com .amazonaws .serverless .proxy .internal .HttpUtils ;
13+ import  com .amazonaws .serverless .proxy .internal .servlet .AwsHttpServletRequest ;
14+ import  com .amazonaws .serverless .proxy .model .RequestSource ;
1315import  org .apache .commons .logging .Log ;
1416import  org .apache .commons .logging .LogFactory ;
1517import  org .springframework .cloud .function .serverless .web .ServerlessHttpServletRequest ;
3638import  jakarta .servlet .ServletContext ;
3739import  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+ 
3944class  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  {
0 commit comments