Skip to content

Commit 88f6e4a

Browse files
committed
GH-754 Fix request parameter parsing
While concentrating on REST we somehow ignored standard request parameters. This fix addresses it for both v1 and v2 requests as well as adds tests and additional endpoint to a sample to verify Resolves #754 polishing
1 parent 58b296f commit 88f6e4a

File tree

5 files changed

+91
-5
lines changed

5 files changed

+91
-5
lines changed

aws-serverless-java-container-springboot3/src/main/java/com/amazonaws/serverless/proxy/spring/AwsSpringHttpProcessingUtils.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
import java.io.InputStream;
44
import java.nio.charset.StandardCharsets;
5+
import java.util.Iterator;
56
import java.util.Map;
7+
import java.util.Map.Entry;
8+
import java.util.Set;
69
import java.util.concurrent.CountDownLatch;
710
import java.util.concurrent.TimeUnit;
811

912
import org.apache.commons.logging.Log;
1013
import org.apache.commons.logging.LogFactory;
1114
import org.springframework.cloud.function.serverless.web.ServerlessHttpServletRequest;
1215
import org.springframework.cloud.function.serverless.web.ServerlessMVC;
16+
import org.springframework.util.CollectionUtils;
1317
import org.springframework.util.FileCopyUtils;
1418
import org.springframework.util.MultiValueMapAdapter;
1519
import org.springframework.util.StringUtils;
@@ -109,6 +113,9 @@ private static HttpServletRequest generateRequest1(String request, Context lambd
109113
AwsProxyRequest v1Request = readValue(request, AwsProxyRequest.class, mapper);
110114

111115
ServerlessHttpServletRequest httpRequest = new ServerlessHttpServletRequest(servletContext, v1Request.getHttpMethod(), v1Request.getPath());
116+
117+
populateQueryStringparameters(v1Request.getQueryStringParameters(), httpRequest);
118+
112119
if (v1Request.getMultiValueHeaders() != null) {
113120
MultiValueMapAdapter headers = new MultiValueMapAdapter(v1Request.getMultiValueHeaders());
114121
httpRequest.setHeaders(headers);
@@ -128,16 +135,21 @@ private static HttpServletRequest generateRequest1(String request, Context lambd
128135
securityWriter.writeSecurityContext(v1Request, lambdaContext));
129136
return httpRequest;
130137
}
138+
139+
131140

132141
@SuppressWarnings({ "rawtypes", "unchecked" })
133142
private static HttpServletRequest generateRequest2(String request, Context lambdaContext,
134143
SecurityContextWriter securityWriter, ObjectMapper mapper, ServletContext servletContext) {
135144
HttpApiV2ProxyRequest v2Request = readValue(request, HttpApiV2ProxyRequest.class, mapper);
145+
146+
136147
ServerlessHttpServletRequest httpRequest = new ServerlessHttpServletRequest(servletContext,
137148
v2Request.getRequestContext().getHttp().getMethod(), v2Request.getRequestContext().getHttp().getPath());
149+
populateQueryStringparameters(v2Request.getQueryStringParameters(), httpRequest);
138150

139151
v2Request.getHeaders().forEach(httpRequest::setHeader);
140-
152+
141153
if (StringUtils.hasText(v2Request.getBody())) {
142154
httpRequest.setContentType("application/json");
143155
httpRequest.setContent(v2Request.getBody().getBytes(StandardCharsets.UTF_8));
@@ -151,6 +163,14 @@ private static HttpServletRequest generateRequest2(String request, Context lambd
151163
return httpRequest;
152164
}
153165

166+
private static void populateQueryStringparameters(Map<String, String> requestParameters, ServerlessHttpServletRequest httpRequest) {
167+
if (!CollectionUtils.isEmpty(requestParameters)) {
168+
for (Entry<String, String> entry : requestParameters.entrySet()) {
169+
httpRequest.setParameter(entry.getKey(), entry.getValue());
170+
}
171+
}
172+
}
173+
154174
private static <T> T readValue(String json, Class<T> clazz, ObjectMapper mapper) {
155175
try {
156176
return mapper.readValue(json, clazz);

aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/SpringDelegatingLambdaContainerHandlerTests.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import org.junit.jupiter.params.ParameterizedTest;
1515
import org.junit.jupiter.params.provider.MethodSource;
16+
import org.springframework.cloud.function.serverless.web.ServerlessServletContext;
1617
import org.springframework.util.CollectionUtils;
1718

1819
import com.amazonaws.serverless.proxy.spring.servletapp.MessageData;
@@ -72,12 +73,16 @@ public class SpringDelegatingLambdaContainerHandlerTests {
7273
+ " },\n"
7374
+ " \"queryStringParameters\": {\n"
7475
+ " \"abc\": \"xyz\",\n"
76+
+ " \"name\": \"Ricky\",\n"
7577
+ " \"foo\": \"baz\"\n"
7678
+ " },\n"
7779
+ " \"multiValueQueryStringParameters\": {\n"
7880
+ " \"abc\": [\n"
7981
+ " \"xyz\"\n"
8082
+ " ],\n"
83+
+ " \"name\": [\n"
84+
+ " \"Ricky\"\n"
85+
+ " ],\n"
8186
+ " \"foo\": [\n"
8287
+ " \"bar\",\n"
8388
+ " \"baz\"\n"
@@ -124,7 +129,7 @@ public class SpringDelegatingLambdaContainerHandlerTests {
124129
" \"version\": \"2.0\",\n" +
125130
" \"routeKey\": \"$default\",\n" +
126131
" \"rawPath\": \"/my/path\",\n" +
127-
" \"rawQueryString\": \"parameter1=value1&parameter1=value2&parameter2=value\",\n" +
132+
" \"rawQueryString\": \"parameter1=value1&parameter1=value2&name=Ricky&parameter2=value\",\n" +
128133
" \"cookies\": [\n" +
129134
" \"cookie1\",\n" +
130135
" \"cookie2\"\n" +
@@ -135,6 +140,7 @@ public class SpringDelegatingLambdaContainerHandlerTests {
135140
" },\n" +
136141
" \"queryStringParameters\": {\n" +
137142
" \"parameter1\": \"value1,value2\",\n" +
143+
" \"name\": \"Ricky\",\n" +
138144
" \"parameter2\": \"value\"\n" +
139145
" },\n" +
140146
" \"requestContext\": {\n" +
@@ -202,6 +208,22 @@ public static Collection<String> data() {
202208
return Arrays.asList(new String[]{API_GATEWAY_EVENT, API_GATEWAY_EVENT_V2});
203209
}
204210

211+
@MethodSource("data")
212+
@ParameterizedTest
213+
public void validateComplesrequest(String jsonEvent) throws Exception {
214+
initServletAppTest();
215+
InputStream targetStream = new ByteArrayInputStream(this.generateHttpRequest(jsonEvent, "POST",
216+
"/foo/male/list/24", "{\"name\":\"bob\"}", null));
217+
ByteArrayOutputStream output = new ByteArrayOutputStream();
218+
handler.handleRequest(targetStream, output, null);
219+
Map result = mapper.readValue(output.toString(StandardCharsets.UTF_8), Map.class);
220+
assertEquals(200, result.get("statusCode"));
221+
String[] respponseBody = ((String) result.get("body")).split("/");
222+
assertEquals("male", respponseBody[0]);
223+
assertEquals("24", respponseBody[1]);
224+
assertEquals("Ricky", respponseBody[2]);
225+
}
226+
205227
@MethodSource("data")
206228
@ParameterizedTest
207229
public void testAsyncPost(String jsonEvent) throws Exception {

aws-serverless-java-container-springboot3/src/test/java/com/amazonaws/serverless/proxy/spring/servletapp/ServletApplication.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package com.amazonaws.serverless.proxy.spring.servletapp;
22

33
import org.springframework.boot.autoconfigure.SpringBootApplication;
4-
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
5-
import org.springframework.context.annotation.ComponentScan;
64
import org.springframework.context.annotation.Import;
5+
import org.springframework.http.MediaType;
6+
import org.springframework.web.bind.annotation.PathVariable;
7+
import org.springframework.web.bind.annotation.RequestMapping;
8+
import org.springframework.web.bind.annotation.RequestMethod;
9+
import org.springframework.web.bind.annotation.RequestParam;
10+
import org.springframework.web.bind.annotation.RestController;
711

812
@SpringBootApplication(exclude = {
913
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration.class,
@@ -14,5 +18,15 @@
1418
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration.class
1519
})
1620
@Import(MessageController.class)
21+
@RestController
1722
public class ServletApplication {
23+
24+
@RequestMapping(path = "/foo/{gender}/list/{age}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
25+
public String complexRequest(
26+
@PathVariable("gender") String gender,
27+
@PathVariable("age") String age,
28+
@RequestParam("name") String name
29+
) {
30+
return gender + "/" + age + "/" + name;
31+
}
1832
}

samples/springboot3/alt-pet-store/README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,21 @@ PetStoreApi - URL for application https://xxxxxxxxxx.execute-api.us-w
3636
---------------------------------------------------------------------------------------------------------
3737
3838
$ curl https://xxxxxxxxxx.execute-api.us-west-2.amazonaws.com/pets
39-
```
39+
```
40+
41+
You can also try a complex request passing both path and request parameters to complex endpoint such as this:
42+
43+
44+
```
45+
@RequestMapping(path = "/foo/{gender}/bar/{age}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
46+
public String complexRequest(@RequestBody String body,
47+
@PathVariable("gender") String gender,
48+
@PathVariable("age") String age,
49+
@RequestParam("name") String name
50+
)
51+
```
52+
For example.
53+
54+
```
55+
curl -d '{"key1":"value1", "key2":"value2"}' -H "Content-Type: application/json" -X POST https://zuhd709386.execute-api.us-east-2.amazonaws.com/foo/male/bar/25?name=Ricky
56+
```

samples/springboot3/alt-pet-store/src/main/java/com/amazonaws/serverless/sample/springboot3/controller/PetsController.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import com.amazonaws.serverless.sample.springboot3.model.Pet;
1818
import com.amazonaws.serverless.sample.springboot3.model.PetData;
1919

20+
import org.springframework.http.MediaType;
21+
import org.springframework.web.bind.annotation.PathVariable;
2022
import org.springframework.web.bind.annotation.RequestBody;
2123
import org.springframework.web.bind.annotation.RequestMapping;
2224
import org.springframework.web.bind.annotation.RequestMethod;
@@ -32,6 +34,7 @@
3234
@RestController
3335
@EnableWebMvc
3436
public class PetsController {
37+
3538
@RequestMapping(path = "/pets", method = RequestMethod.POST)
3639
public Pet createPet(@RequestBody Pet newPet) {
3740
if (newPet.getName() == null || newPet.getBreed() == null) {
@@ -73,5 +76,15 @@ public Pet listPets() {
7376
newPet.setName(PetData.getRandomName());
7477
return newPet;
7578
}
79+
80+
@RequestMapping(path = "/foo/{gender}/bar/{age}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
81+
public String complexRequest(@RequestBody String body,
82+
@PathVariable("gender") String gender,
83+
@PathVariable("age") String age,
84+
@RequestParam("name") String name
85+
) {
86+
System.out.println("Body: " + body + " - " + gender + "/" + age + "/" + name);
87+
return gender + "/" + age + "/" + name;
88+
}
7689

7790
}

0 commit comments

Comments
 (0)