[ https://issues.apache.org/jira/browse/NIFI-3469?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16645846#comment-16645846 ]
ASF GitHub Bot commented on NIFI-3469: -------------------------------------- Github user ijokarumawak commented on a diff in the pull request: https://github.com/apache/nifi/pull/2991#discussion_r224003310 --- Diff: nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/HandleHttpRequest.java --- @@ -521,161 +565,223 @@ public void onTrigger(final ProcessContext context, final ProcessSession session final long start = System.nanoTime(); final HttpServletRequest request = container.getRequest(); - FlowFile flowFile = session.create(); - try (OutputStream flowFileOut = session.write(flowFile)) { - StreamUtils.copy(request.getInputStream(), flowFileOut); - } catch (final IOException e) { - // There may be many reasons which can produce an IOException on the HTTP stream and in some of them, eg. - // bad requests, the connection to the client is not closed. In order to address also these cases, we try - // and answer with a BAD_REQUEST, which lets the client know that the request has not been correctly - // processed and makes it aware that the connection can be closed. - getLogger().error("Failed to receive content from HTTP Request from {} due to {}", - new Object[]{request.getRemoteAddr(), e}); - session.remove(flowFile); - try { - HttpServletResponse response = container.getResponse(); - response.sendError(Status.BAD_REQUEST.getStatusCode()); - response.flushBuffer(); - container.getContext().complete(); - } catch (final IOException ioe) { - getLogger().warn("Failed to send HTTP response to {} due to {}", - new Object[]{request.getRemoteAddr(), ioe}); + if (!Strings.isNullOrEmpty(request.getContentType()) && request.getContentType().contains(MIME_TYPE__MULTIPART_FORM_DATA)) { + final long requestMaxSize = context.getProperty(MULTIPART_REQUEST_MAX_SIZE).asDataSize(DataUnit.B).longValue(); + final int readBufferSize = context.getProperty(MULTIPART_READ_BUFFER_SIZE).asDataSize(DataUnit.B).intValue(); + String tempDir = System.getProperty("java.io.tmpdir"); + request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, new MultipartConfigElement(tempDir, requestMaxSize, requestMaxSize, readBufferSize)); + try { + List<Part> parts = ImmutableList.copyOf(request.getParts()); + int allPartsCount = parts.size(); + final String contextIdentifier = UUID.randomUUID().toString(); + for (int i = 0; i < allPartsCount; i++) { + Part part = parts.get(i); + FlowFile flowFile = session.create(); + try (OutputStream flowFileOut = session.write(flowFile)) { + StreamUtils.copy(part.getInputStream(), flowFileOut); + } catch (IOException e) { + handleFlowContentStreamingError(session, container, request, Optional.of(flowFile), e); + return; + } + flowFile = savePartAttributes(context, session, part, flowFile, i, allPartsCount); + flowFile = saveRequestAttributes(context, session, request, flowFile, contextIdentifier); + forwardFlowFile(context, session, container, start, request, flowFile, i == 0); --- End diff -- What if `contextMap.register()` method returns `false`? I haven't test that, but current code seems to keep processing remaining multi-part. The register part should be a separated method and return if the request is successfully registered, so that this `allPartsCount` loop can break. Adding a unit test case to confirm that situation would be helpful. > Add multipart request support to HandleHttpRequest Processor > ------------------------------------------------------------ > > Key: NIFI-3469 > URL: https://issues.apache.org/jira/browse/NIFI-3469 > Project: Apache NiFi > Issue Type: Improvement > Components: Extensions > Reporter: Koji Kawamura > Assignee: Endre Kovacs > Priority: Major > > Currently, HandleHttpRequest outputs a single FlowFile containing all > multipart values as following: > {code} > --------------------------ef07e8bf36c274d3 > Content-Disposition: form-data; name="p1" > v1 > --------------------------ef07e8bf36c274d3 > Content-Disposition: form-data; name="p2" > v2 > --------------------------ef07e8bf36c274d3-- > {code} > Many users requested adding upload files support to NiFi. > In order for HandleHttpRequest to support multipart data we need to add > followings (this is based on a brief researching and can be more complex or > simple): > We need to use HttpServletRequest#getParts() as written in this stackoverflow > thread: > http://stackoverflow.com/questions/3337056/convenient-way-to-parse-incoming-multipart-form-data-parameters-in-a-servlet > Also, we probably need a custom MultiPartInputStreamParser implementation. > Because Jetty's default implementation writes input data to temporary > directory on file system, instead, we'd like NiFi to write those into output > FlowFiles content in streaming fashion. > And we need request size validation checks, threshold for those validation > should be passed via javax.servlet.MultipartConfigElement. > Finally, we have to do something with HandleHttpResponse processor. > Once HandleHttpRequest processor start splitting incoming request into > multiple output FlowFiles, we need to wait for every fragment to be > processed, then execute HandleHttpRequest. > I think Wait/Notify processors (available from next version) will be helpful > here. -- This message was sent by Atlassian JIRA (v7.6.3#76005)