Detect RawInput correctly
Some endpoints allow both JSON and raw input. parseRequest selects
whether to parse to JSON using a reader or to provide the raw input as
an InputStream based on the request's content-type.
Since v2.15-rc0~1847^2 (Discard request HTTP bodies before writing
response, 2017-03-16), on endpoints that permit raw input, we call
getInputStream to obtain the rest of the response body and discard it
before writing the response. When the request was JSON, this produces
errors from Jetty, since calling getInputStream after getReader violates
the servlet API:
[HTTP-66] ERROR com.google.gerrit.httpd.restapi.RestApiServlet : Error in PUT /a/plugins/reviewers.jar
java.lang.IllegalStateException: READER
at org.eclipse.jetty.server.Request.getInputStream(Request.java:844)
at javax.servlet.ServletRequestWrapper.getInputStream(ServletRequestWrapper.java:138)
at javax.servlet.ServletRequestWrapper.getInputStream(ServletRequestWrapper.java:138)
To fix it, instead of guessing whether this was a raw request based on
whether the endpoint supports raw requests, use the parseRequest result
to decide whether this is a raw request for which we need to discard any
unconsumed content.
Bug: Issue 8677
Change-Id: I1db69104f31e1c04b137d994523422a07ca5cf43
(cherry picked from commit 91136bb28e)
This commit is contained in:
committed by
Jonathan Nieder
parent
17783eed70
commit
8271f4588c
@@ -403,7 +403,11 @@ public class RestApiServlet extends HttpServlet {
|
||||
Type type = inputType(m);
|
||||
inputRequestBody = parseRequest(req, type);
|
||||
result = m.apply(rsrc, inputRequestBody);
|
||||
consumeRawInputRequestBody(req, type);
|
||||
if (inputRequestBody instanceof RawInput) {
|
||||
try (InputStream is = req.getInputStream()) {
|
||||
ServletUtils.consumeRequestBody(is);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
@@ -750,7 +754,9 @@ public class RestApiServlet extends HttpServlet {
|
||||
br.skip(Long.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
} else if (rawInputRequest(req, type)) {
|
||||
}
|
||||
String method = req.getMethod();
|
||||
if (("PUT".equals(method) || "POST".equals(method)) && acceptsRawInput(type)) {
|
||||
return parseRawInput(req, type);
|
||||
} else if ("DELETE".equals(req.getMethod()) && hasNoBody(req)) {
|
||||
return null;
|
||||
@@ -773,19 +779,6 @@ public class RestApiServlet extends HttpServlet {
|
||||
}
|
||||
}
|
||||
|
||||
private void consumeRawInputRequestBody(HttpServletRequest req, Type type) throws IOException {
|
||||
if (rawInputRequest(req, type)) {
|
||||
try (InputStream is = req.getInputStream()) {
|
||||
ServletUtils.consumeRequestBody(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean rawInputRequest(HttpServletRequest req, Type type) {
|
||||
String method = req.getMethod();
|
||||
return ("PUT".equals(method) || "POST".equals(method)) && acceptsRawInput(type);
|
||||
}
|
||||
|
||||
private static boolean hasNoBody(HttpServletRequest req) {
|
||||
int len = req.getContentLength();
|
||||
String type = req.getContentType();
|
||||
|
||||
Reference in New Issue
Block a user