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