Allow empty request body for POST/PUT/DELETE REST endpoints that expect List/Map as input
If a REST endpoint expects a List or a Map as input, but the user provides an empty request body we currently fail with 500 Internal Server Error, e.g.: POST /accounts/<account-id>/watched.projects Instead just create an empty List/Map and provide it to the REST endpoint. This is consistent with instantiating empty Input objects when the REST endpoint expects a non-generic input type and the user provides no body. Change-Id: I78fe66b2d0f63a6078411dd50a55196424d88490 Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
@@ -846,16 +846,25 @@ public class RestApiServlet extends HttpServlet {
|
|||||||
throw new BadRequestException("Expected JSON object");
|
throw new BadRequestException("Expected JSON object");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private static Object createInstance(Type type)
|
private static Object createInstance(Type type)
|
||||||
throws NoSuchMethodException, InstantiationException, IllegalAccessException,
|
throws NoSuchMethodException, InstantiationException, IllegalAccessException,
|
||||||
InvocationTargetException {
|
InvocationTargetException {
|
||||||
if (type instanceof Class) {
|
if (type instanceof Class) {
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Class<Object> clazz = (Class<Object>) type;
|
Class<Object> clazz = (Class<Object>) type;
|
||||||
Constructor<Object> c = clazz.getDeclaredConstructor();
|
Constructor<Object> c = clazz.getDeclaredConstructor();
|
||||||
c.setAccessible(true);
|
c.setAccessible(true);
|
||||||
return c.newInstance();
|
return c.newInstance();
|
||||||
}
|
}
|
||||||
|
if (type instanceof ParameterizedType) {
|
||||||
|
Type rawType = ((ParameterizedType) type).getRawType();
|
||||||
|
if (rawType instanceof Class && List.class.isAssignableFrom((Class<Object>) rawType)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (rawType instanceof Class && Map.class.isAssignableFrom((Class<Object>) rawType)) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
throw new InstantiationException("Cannot make " + type);
|
throw new InstantiationException("Cannot make " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -235,4 +235,9 @@ public class WatchedProjectsIT extends AbstractDaemonTest {
|
|||||||
assertThat(persistedWatchedProjects).doesNotContain(pwi);
|
assertThat(persistedWatchedProjects).doesNotContain(pwi);
|
||||||
assertThat(persistedWatchedProjects).containsAllIn(projectsToWatch);
|
assertThat(persistedWatchedProjects).containsAllIn(projectsToWatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void postWithoutBody() throws Exception {
|
||||||
|
adminRestSession.post("/accounts/" + admin.username + "/watched.projects").assertOK();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user