|
31 | 31 | import com.fasterxml.jackson.databind.node.ArrayNode; |
32 | 32 | import com.fasterxml.jackson.databind.node.ObjectNode; |
33 | 33 |
|
| 34 | +import org.apache.commons.fileupload.FileItemIterator; |
| 35 | +import org.apache.commons.fileupload.FileItemStream; |
| 36 | +import org.apache.commons.fileupload.FileUploadException; |
| 37 | +import org.apache.commons.fileupload.servlet.ServletFileUpload; |
| 38 | + |
34 | 39 | import java.io.IOException; |
35 | 40 | import java.lang.reflect.InvocationTargetException; |
36 | | -import java.util.Collection; |
37 | 41 | import java.util.Enumeration; |
38 | 42 | import java.util.List; |
39 | 43 | import java.util.Map; |
@@ -83,13 +87,35 @@ public Object[] read() throws ServiceException { |
83 | 87 | return new Object[0]; |
84 | 88 | } |
85 | 89 | HttpServletRequest servletRequest = endpointsContext.getRequest(); |
86 | | - String requestBody = IoUtil.readRequestBody(servletRequest); |
87 | | - logger.log(Level.FINE, "requestBody=" + requestBody); |
88 | | - // Unlike the Lily protocol, which essentially always requires a JSON body to exist (due to |
89 | | - // path and query parameters being injected into the body), bodies are optional here, so we |
90 | | - // create an empty body and inject named parameters to make deserialize work. |
91 | | - JsonNode node = Strings.isEmptyOrWhitespace(requestBody) ? objectReader.createObjectNode() |
92 | | - : objectReader.readTree(requestBody); |
| 90 | + JsonNode node; |
| 91 | + // multipart/form-data requests can be used for requests which have no resource body. In |
| 92 | + // this case, each part represents a named parameter instead. |
| 93 | + if (ServletFileUpload.isMultipartContent(servletRequest)) { |
| 94 | + try { |
| 95 | + ServletFileUpload upload = new ServletFileUpload(); |
| 96 | + FileItemIterator iter = upload.getItemIterator(servletRequest); |
| 97 | + ObjectNode obj = (ObjectNode) objectReader.createObjectNode(); |
| 98 | + while (iter.hasNext()) { |
| 99 | + FileItemStream item = iter.next(); |
| 100 | + if (item.isFormField()) { |
| 101 | + obj.put(item.getFieldName(), IoUtil.readStream(item.openStream())); |
| 102 | + } else { |
| 103 | + throw new BadRequestException("unable to parse multipart form field"); |
| 104 | + } |
| 105 | + } |
| 106 | + node = obj; |
| 107 | + } catch (FileUploadException e) { |
| 108 | + throw new BadRequestException("unable to parse multipart request", e); |
| 109 | + } |
| 110 | + } else { |
| 111 | + String requestBody = IoUtil.readRequestBody(servletRequest); |
| 112 | + logger.log(Level.FINE, "requestBody=" + requestBody); |
| 113 | + // Unlike the Lily protocol, which essentially always requires a JSON body to exist (due to |
| 114 | + // path and query parameters being injected into the body), bodies are optional here, so we |
| 115 | + // create an empty body and inject named parameters to make deserialize work. |
| 116 | + node = Strings.isEmptyOrWhitespace(requestBody) ? objectReader.createObjectNode() |
| 117 | + : objectReader.readTree(requestBody); |
| 118 | + } |
93 | 119 | if (!node.isObject()) { |
94 | 120 | throw new BadRequestException("expected a JSON object body"); |
95 | 121 | } |
|
0 commit comments