diff options
author | Masaya Suzuki <masayasuzuki@google.com> | 2018-04-02 15:40:40 -0700 |
---|---|---|
committer | Jonathan Nieder <jrn@google.com> | 2018-04-03 12:53:11 -0700 |
commit | 8271f4588c909e66746985cd621c7db3755c301d (patch) | |
tree | 397642d7b590056c5d2a1ceed75b6fa3d9968bcb | |
parent | 17783eed7010028370455030b04098ec298f3447 (diff) |
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 91136bb28ec45cbbd66e7d8aabe209a6faa7eb2a)
-rw-r--r-- | gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java | 23 |
1 files changed, 8 insertions, 15 deletions
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java index d1e4e88915..4d4ef8e92c 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java @@ -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(); |