Remove flowfiles and close connection for Bad Requests causing IOException
This closes
@@ -39,6 +39,7 @@ import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.processors.standard.util.HTTPUtils;
import org.apache.nifi.ssl.RestrictedSSLContextService;
import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.stream.io.StreamUtils;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
@@ -58,6 +59,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.Response.Status;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -513,12 +515,26 @@ public class HandleHttpRequest extends AbstractProcessor {
final long start = System.nanoTime();
final HttpServletRequest request = container.getRequest();
FlowFile flowFile = session.create();
- try {
- flowFile = session.importFrom(request.getInputStream(), flowFile);
+ 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});
+ }
return;
}
