use of org.apache.nifi.remote.exception.RequestExpiredException in project nifi by apache.
the class DataTransferResource method transferFlowFiles.
@GET
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Path("output-ports/{portId}/transactions/{transactionId}/flow-files")
@ApiOperation(value = "Transfer flow files from the output port", response = StreamingOutput.class, authorizations = { @Authorization(value = "Write - /data-transfer/output-ports/{uuid}") })
@ApiResponses(value = { @ApiResponse(code = 200, message = "There is no flow file to return."), @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."), @ApiResponse(code = 401, message = "Client could not be authenticated."), @ApiResponse(code = 403, message = "Client is not authorized to make this request."), @ApiResponse(code = 404, message = "The specified resource could not be found."), @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful."), @ApiResponse(code = 503, message = "NiFi instance is not ready for serving request, or temporarily overloaded. Retrying the same request later may be successful") })
public Response transferFlowFiles(@ApiParam(value = "The output port id.", required = true) @PathParam("portId") String portId, @PathParam("transactionId") String transactionId, @Context HttpServletRequest req, @Context HttpServletResponse res, @Context ServletContext context, InputStream inputStream) {
// authorize access
serviceFacade.authorizeAccess(lookup -> {
authorizeDataTransfer(lookup, ResourceType.OutputPort, portId);
});
final ValidateRequestResult validationResult = validateResult(req, portId, transactionId);
if (validationResult.errResponse != null) {
return validationResult.errResponse;
}
logger.debug("transferFlowFiles request: portId={}", portId);
// Before opening the real output stream for HTTP response,
// use this temporary output stream to buffer handshake result.
final ByteArrayOutputStream tempBos = new ByteArrayOutputStream();
final Peer peer = constructPeer(req, inputStream, tempBos, portId, transactionId);
final int transportProtocolVersion = validationResult.transportProtocolVersion;
try {
final HttpFlowFileServerProtocol serverProtocol = initiateServerProtocol(req, peer, transportProtocolVersion);
StreamingOutput flowFileContent = new StreamingOutput() {
@Override
public void write(OutputStream outputStream) throws IOException, WebApplicationException {
HttpOutput output = (HttpOutput) peer.getCommunicationsSession().getOutput();
output.setOutputStream(outputStream);
try {
int numOfFlowFiles = serverProtocol.getPort().transferFlowFiles(peer, serverProtocol);
logger.debug("finished transferring flow files, numOfFlowFiles={}", numOfFlowFiles);
if (numOfFlowFiles < 1) {
// There was no flow file to transfer. Throw this exception to stop responding with SEE OTHER.
throw new WebApplicationException(Response.Status.OK);
}
} catch (NotAuthorizedException | BadRequestException | RequestExpiredException e) {
// Handshake is done outside of write() method, so these exception wouldn't be thrown.
throw new IOException("Failed to process the request.", e);
}
}
};
return responseCreator.acceptedResponse(transactionManager, flowFileContent, transportProtocolVersion);
} catch (HandshakeException e) {
return responseCreator.handshakeExceptionResponse(e);
} catch (Exception e) {
return responseCreator.unexpectedErrorResponse(portId, e);
}
}
use of org.apache.nifi.remote.exception.RequestExpiredException in project nifi by apache.
the class StandardRootGroupPort method transferFlowFiles.
@Override
public int transferFlowFiles(final Peer peer, final ServerProtocol serverProtocol) throws NotAuthorizedException, BadRequestException, RequestExpiredException {
if (getConnectableType() != ConnectableType.OUTPUT_PORT) {
throw new IllegalStateException("Cannot send FlowFiles because this port is not an Output Port");
}
if (!this.isRunning()) {
throw new IllegalStateException("Port not running");
}
try {
final FlowFileRequest request = new FlowFileRequest(peer, serverProtocol);
if (!this.requestQueue.offer(request)) {
throw new RequestExpiredException();
}
// Trigger this port to run
scheduler.registerEvent(this);
// Get a response from the response queue but don't wait forever if the port is stopped
ProcessingResult result = null;
// before the request expires
while (!request.isBeingServiced()) {
if (request.isExpired()) {
// Remove expired request, so that it won't block new request to be offered.
this.requestQueue.remove(request);
throw new SocketTimeoutException("Read timed out");
} else {
try {
Thread.sleep(100L);
} catch (final InterruptedException e) {
}
}
}
// we've started to service the request. Now just wait until it's finished
result = request.getResponseQueue().take();
final Exception problem = result.getProblem();
if (problem == null) {
return result.getFileCount();
} else {
throw problem;
}
} catch (final NotAuthorizedException | BadRequestException | RequestExpiredException e) {
throw e;
} catch (final ProtocolException e) {
throw new BadRequestException(e);
} catch (final Exception e) {
throw new ProcessException(e);
}
}
use of org.apache.nifi.remote.exception.RequestExpiredException in project nifi by apache.
the class StandardRootGroupPort method receiveFlowFiles.
@Override
public int receiveFlowFiles(final Peer peer, final ServerProtocol serverProtocol) throws NotAuthorizedException, BadRequestException, RequestExpiredException {
if (getConnectableType() != ConnectableType.INPUT_PORT) {
throw new IllegalStateException("Cannot receive FlowFiles because this port is not an Input Port");
}
if (!this.isRunning()) {
throw new IllegalStateException("Port not running");
}
try {
final FlowFileRequest request = new FlowFileRequest(peer, serverProtocol);
if (!this.requestQueue.offer(request)) {
throw new RequestExpiredException();
}
// Trigger this port to run.
scheduler.registerEvent(this);
// Get a response from the response queue but don't wait forever if the port is stopped
ProcessingResult result = null;
// before the request expires
while (!request.isBeingServiced()) {
if (request.isExpired()) {
// Remove expired request, so that it won't block new request to be offered.
this.requestQueue.remove(request);
throw new SocketTimeoutException("Read timed out");
} else {
try {
Thread.sleep(100L);
} catch (final InterruptedException e) {
}
}
}
// we've started to service the request. Now just wait until it's finished
result = request.getResponseQueue().take();
final Exception problem = result.getProblem();
if (problem == null) {
return result.getFileCount();
} else {
throw problem;
}
} catch (final NotAuthorizedException | BadRequestException | RequestExpiredException e) {
throw e;
} catch (final ProtocolException e) {
throw new BadRequestException(e);
} catch (final Exception e) {
throw new ProcessException(e);
}
}
use of org.apache.nifi.remote.exception.RequestExpiredException in project nifi by apache.
the class StandardRootGroupPort method onTrigger.
private void onTrigger(final ProcessContext context, final ProcessSession session, final FlowFileRequest flowFileRequest) {
final ServerProtocol protocol = flowFileRequest.getProtocol();
final BlockingQueue<ProcessingResult> responseQueue = flowFileRequest.getResponseQueue();
if (flowFileRequest.isExpired()) {
final String message = String.format("%s Cannot service request from %s because the request has timed out", this, flowFileRequest.getPeer());
logger.warn(message);
eventReporter.reportEvent(Severity.WARNING, CATEGORY, message);
responseQueue.add(new ProcessingResult(new RequestExpiredException()));
return;
}
final Peer peer = flowFileRequest.getPeer();
final CommunicationsSession commsSession = peer.getCommunicationsSession();
final String sourceDn = commsSession.getUserDn();
logger.debug("{} Servicing request for {} (DN={})", this, peer, sourceDn);
final PortAuthorizationResult authorizationResult = checkUserAuthorization(sourceDn);
if (!authorizationResult.isAuthorized()) {
final String message = String.format("%s Cannot service request from %s (DN=%s) because peer is not authorized to communicate with this port: %s", this, flowFileRequest.getPeer(), flowFileRequest.getPeer().getCommunicationsSession().getUserDn(), authorizationResult.getExplanation());
logger.error(message);
eventReporter.reportEvent(Severity.ERROR, CATEGORY, message);
responseQueue.add(new ProcessingResult(new NotAuthorizedException(authorizationResult.getExplanation())));
return;
}
final FlowFileCodec codec = protocol.getPreNegotiatedCodec();
if (codec == null) {
responseQueue.add(new ProcessingResult(new BadRequestException("None of the supported FlowFile Codecs supplied is compatible with this instance")));
return;
}
final int transferCount;
try {
if (getConnectableType() == ConnectableType.INPUT_PORT) {
transferCount = receiveFlowFiles(context, session, codec, flowFileRequest);
} else {
transferCount = transferFlowFiles(context, session, codec, flowFileRequest);
}
} catch (final IOException e) {
session.rollback();
responseQueue.add(new ProcessingResult(e));
return;
} catch (final Exception e) {
session.rollback();
responseQueue.add(new ProcessingResult(e));
return;
}
// TODO: Comfirm this. Session.commit here is not required since it has been committed inside receiveFlowFiles/transferFlowFiles.
// session.commit();
responseQueue.add(new ProcessingResult(transferCount));
}
use of org.apache.nifi.remote.exception.RequestExpiredException in project nifi by apache.
the class DataTransferResource method receiveFlowFiles.
@POST
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Produces(MediaType.TEXT_PLAIN)
@Path("input-ports/{portId}/transactions/{transactionId}/flow-files")
@ApiOperation(value = "Transfer flow files to the input port", response = String.class, authorizations = { @Authorization(value = "Write - /data-transfer/input-ports/{uuid}") })
@ApiResponses(value = { @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."), @ApiResponse(code = 401, message = "Client could not be authenticated."), @ApiResponse(code = 403, message = "Client is not authorized to make this request."), @ApiResponse(code = 404, message = "The specified resource could not be found."), @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful."), @ApiResponse(code = 503, message = "NiFi instance is not ready for serving request, or temporarily overloaded. Retrying the same request later may be successful") })
public Response receiveFlowFiles(@ApiParam(value = "The input port id.", required = true) @PathParam("portId") String portId, @PathParam("transactionId") String transactionId, @Context HttpServletRequest req, @Context ServletContext context, InputStream inputStream) {
// authorize access
serviceFacade.authorizeAccess(lookup -> {
authorizeDataTransfer(lookup, ResourceType.InputPort, portId);
});
final ValidateRequestResult validationResult = validateResult(req, portId, transactionId);
if (validationResult.errResponse != null) {
return validationResult.errResponse;
}
logger.debug("receiveFlowFiles request: portId={}", portId);
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final Peer peer = constructPeer(req, inputStream, out, portId, transactionId);
final int transportProtocolVersion = validationResult.transportProtocolVersion;
try {
HttpFlowFileServerProtocol serverProtocol = initiateServerProtocol(req, peer, transportProtocolVersion);
int numOfFlowFiles = serverProtocol.getPort().receiveFlowFiles(peer, serverProtocol);
logger.debug("finished receiving flow files, numOfFlowFiles={}", numOfFlowFiles);
if (numOfFlowFiles < 1) {
return Response.status(Response.Status.BAD_REQUEST).entity("Client should send request when there is data to send. There was no flow file sent.").build();
}
} catch (HandshakeException e) {
return responseCreator.handshakeExceptionResponse(e);
} catch (NotAuthorizedException e) {
return responseCreator.unauthorizedResponse(e);
} catch (BadRequestException | RequestExpiredException e) {
return responseCreator.badRequestResponse(e);
} catch (Exception e) {
return responseCreator.unexpectedErrorResponse(portId, e);
}
String serverChecksum = ((HttpServerCommunicationsSession) peer.getCommunicationsSession()).getChecksum();
return responseCreator.acceptedResponse(transactionManager, serverChecksum, transportProtocolVersion);
}
Aggregations