Skip to content
This repository was archived by the owner on Jun 30, 2023. It is now read-only.

Commit 8378711

Browse files
committed
fix array path parameter deserialization
This change fixes path parameter deserialization when the parameter is an array-like structure. Previously, this only worked for query parameters, and a string literal was injected as an array for path parameters.
1 parent 968f420 commit 8378711

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

endpoints-framework/src/main/java/com/google/api/server/spi/request/RestServletRequestParamReader.java

+13-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.google.api.server.spi.config.model.ApiParameterConfig;
2424
import com.google.api.server.spi.config.model.ApiSerializationConfig;
2525
import com.google.api.server.spi.response.BadRequestException;
26+
import com.google.common.base.Splitter;
2627
import com.google.common.collect.ImmutableMap;
2728

2829
import com.fasterxml.jackson.databind.JsonNode;
@@ -31,6 +32,7 @@
3132

3233
import java.io.IOException;
3334
import java.lang.reflect.InvocationTargetException;
35+
import java.util.Collection;
3436
import java.util.Enumeration;
3537
import java.util.List;
3638
import java.util.Map;
@@ -48,8 +50,10 @@
4850
* by stuffing path and query parameters into the main request body.
4951
*/
5052
public class RestServletRequestParamReader extends ServletRequestParamReader {
53+
5154
private static final Logger logger = Logger
5255
.getLogger(RestServletRequestParamReader.class.getName());
56+
private static final Splitter COMPOSITE_PATH_SPLITTER = Splitter.on(',');
5357

5458
private final Map<String, String> rawPathParameters;
5559
private final Map<String, ApiParameterConfig> parameterConfigMap;
@@ -99,11 +103,10 @@ public Object[] read() throws ServiceException {
99103
Class<?> parameterClass = parameterMap.get(parameterName);
100104
ApiParameterConfig parameterConfig = parameterConfigMap.get(parameterName);
101105
if (parameterClass != null && parameterConfig.isRepeated()) {
102-
ArrayNode values = (ArrayNode) objectReader.createArrayNode();
106+
ArrayNode values = body.putArray(parameterName);
103107
for (String value : servletRequest.getParameterValues(parameterName)) {
104108
values.add(value);
105109
}
106-
body.set(parameterName, values);
107110
} else {
108111
body.put(parameterName, servletRequest.getParameterValues(parameterName)[0]);
109112
}
@@ -113,7 +116,14 @@ public Object[] read() throws ServiceException {
113116
String parameterName = entry.getKey();
114117
Class<?> parameterClass = parameterMap.get(parameterName);
115118
if (parameterClass != null && !body.has(parameterName)) {
116-
body.put(parameterName, entry.getValue());
119+
if (parameterConfigMap.get(parameterName).isRepeated()) {
120+
ArrayNode values = body.putArray(parameterName);
121+
for (String value : COMPOSITE_PATH_SPLITTER.split(entry.getValue())) {
122+
values.add(value);
123+
}
124+
} else {
125+
body.put(parameterName, entry.getValue());
126+
}
117127
}
118128
}
119129
for (Entry<String, ApiParameterConfig> entry : parameterConfigMap.entrySet()) {

endpoints-framework/src/test/java/com/google/api/server/spi/request/RestServletRequestParamReaderTest.java

+27-5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.google.common.collect.ImmutableList;
3636
import com.google.common.collect.ImmutableMap;
3737

38+
import java.util.ArrayList;
3839
import org.junit.Before;
3940
import org.junit.Test;
4041
import org.junit.runner.RunWith;
@@ -61,6 +62,7 @@ public class RestServletRequestParamReaderTest {
6162
private EndpointMethod endpointMethod;
6263
private MockHttpServletRequest request;
6364
private ApiSerializationConfig serializationConfig;
65+
private ApiConfig apiConfig;
6466
private ApiMethodConfig methodConfig;
6567

6668
@Before
@@ -72,13 +74,12 @@ public void setUp() throws Exception {
7274
ServiceContext serviceContext = ServiceContext.create();
7375
serializationConfig = new ApiSerializationConfig();
7476
TypeLoader typeLoader = new TypeLoader();
75-
ApiConfig config = (new ApiConfig.Factory()).create(serviceContext, typeLoader,
76-
TestApi.class);
77+
apiConfig = new ApiConfig.Factory().create(serviceContext, typeLoader, TestApi.class);
7778
ApiConfigAnnotationReader annotationReader = new ApiConfigAnnotationReader();
78-
annotationReader.loadEndpointClass(serviceContext, TestApi.class, config);
79+
annotationReader.loadEndpointClass(serviceContext, TestApi.class, apiConfig);
7980
annotationReader.loadEndpointMethods(serviceContext, TestApi.class,
80-
config.getApiClassConfig().getMethods());
81-
methodConfig = config.getApiClassConfig().getMethods().get(endpointMethod);
81+
apiConfig.getApiClassConfig().getMethods());
82+
methodConfig = apiConfig.getApiClassConfig().getMethods().get(endpointMethod);
8283
}
8384

8485
@Test
@@ -186,6 +187,20 @@ public void gzippedRequest() throws Exception {
186187
.inOrder();
187188
}
188189

190+
@Test
191+
public void arrayPathParam() throws Exception {
192+
endpointMethod = EndpointMethod.create(TestApi.class,
193+
TestApi.class.getMethod("testArrayPathParam", ArrayList.class));
194+
methodConfig = apiConfig.getApiClassConfig().getMethods().get(endpointMethod);
195+
RestServletRequestParamReader reader = createReader(ImmutableMap.of("values", "4,3,2,1"));
196+
197+
Object[] params = reader.read();
198+
199+
assertThat(params).hasLength(endpointMethod.getParameterClasses().length);
200+
assertThat(params).asList()
201+
.containsExactly(ImmutableList.of("4", "3", "2", "1"));
202+
}
203+
189204
private RestServletRequestParamReader createReader(Map<String, String> rawPathParameters) {
190205
return new RestServletRequestParamReader(endpointMethod, request, null,
191206
serializationConfig, methodConfig, rawPathParameters);
@@ -213,6 +228,13 @@ public void test(@Named("path") long path, @Named("dates") List<SimpleDate> date
213228
@Named("defaultvalue") @DefaultValue("2015-01-01") SimpleDate defaultValue,
214229
TestResource resource) {
215230
}
231+
232+
@ApiMethod(
233+
name = "testArrayPathParam",
234+
httpMethod = HttpMethod.GET,
235+
path = "testArrayPathParam/{values}")
236+
public void testArrayPathParam(@Named("values") ArrayList<String> values) {
237+
}
216238
}
217239

218240
private static byte[] compress(byte[] bytes) {

0 commit comments

Comments
 (0)