use of org.apache.nifi.remote.protocol.http.HttpFlowFileServerProtocol 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.protocol.http.HttpFlowFileServerProtocol in project nifi by apache.
the class TestDataTransferResource method testCreateTransactionPortNotFound.
@Test
public void testCreateTransactionPortNotFound() throws Exception {
final HttpServletRequest req = createCommonHttpServletRequest();
final DataTransferResource resource = getDataTransferResource();
final HttpFlowFileServerProtocol serverProtocol = resource.getHttpFlowFileServerProtocol(null);
doThrow(new HandshakeException(ResponseCode.UNKNOWN_PORT, "Not found.")).when(serverProtocol).handshake(any());
final ServletContext context = null;
final UriInfo uriInfo = null;
final InputStream inputStream = null;
final Response response = resource.createPortTransaction("input-ports", "port-id", req, context, uriInfo, inputStream);
TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
assertEquals(404, response.getStatus());
assertEquals(ResponseCode.UNKNOWN_PORT.getCode(), resultEntity.getResponseCode());
}
use of org.apache.nifi.remote.protocol.http.HttpFlowFileServerProtocol in project nifi by apache.
the class TestDataTransferResource method testCreateTransactionPortNotInValidState.
@Test
public void testCreateTransactionPortNotInValidState() throws Exception {
final HttpServletRequest req = createCommonHttpServletRequest();
final DataTransferResource resource = getDataTransferResource();
final HttpFlowFileServerProtocol serverProtocol = resource.getHttpFlowFileServerProtocol(null);
doThrow(new HandshakeException(ResponseCode.PORT_NOT_IN_VALID_STATE, "Not in valid state.")).when(serverProtocol).handshake(any());
final ServletContext context = null;
final UriInfo uriInfo = null;
final InputStream inputStream = null;
final Response response = resource.createPortTransaction("input-ports", "port-id", req, context, uriInfo, inputStream);
TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
assertEquals(503, response.getStatus());
assertEquals(ResponseCode.PORT_NOT_IN_VALID_STATE.getCode(), resultEntity.getResponseCode());
}
use of org.apache.nifi.remote.protocol.http.HttpFlowFileServerProtocol in project nifi by apache.
the class TestDataTransferResource method testCreateTransactionUnauthorized.
@Test
public void testCreateTransactionUnauthorized() throws Exception {
final HttpServletRequest req = createCommonHttpServletRequest();
final DataTransferResource resource = getDataTransferResource();
final HttpFlowFileServerProtocol serverProtocol = resource.getHttpFlowFileServerProtocol(null);
doThrow(new HandshakeException(ResponseCode.UNAUTHORIZED, "Unauthorized.")).when(serverProtocol).handshake(any());
final ServletContext context = null;
final UriInfo uriInfo = null;
final InputStream inputStream = null;
final Response response = resource.createPortTransaction("input-ports", "port-id", req, context, uriInfo, inputStream);
TransactionResultEntity resultEntity = (TransactionResultEntity) response.getEntity();
assertEquals(401, response.getStatus());
assertEquals(ResponseCode.UNAUTHORIZED.getCode(), resultEntity.getResponseCode());
}
use of org.apache.nifi.remote.protocol.http.HttpFlowFileServerProtocol in project nifi by apache.
the class DataTransferResource method commitOutputPortTransaction.
@DELETE
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Produces(MediaType.APPLICATION_JSON)
@Path("output-ports/{portId}/transactions/{transactionId}")
@ApiOperation(value = "Commit or cancel the specified transaction", response = TransactionResultEntity.class, authorizations = { @Authorization(value = "Write - /data-transfer/output-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 commitOutputPortTransaction(@ApiParam(value = "The response code. Available values are CONFIRM_TRANSACTION(12) or CANCEL_TRANSACTION(15).", required = true) @QueryParam(RESPONSE_CODE) Integer responseCode, @ApiParam(value = "A checksum calculated at client side using CRC32 to check flow file content integrity. It must match with the value calculated at server side.", required = true) @QueryParam(CHECK_SUM) @DefaultValue(StringUtils.EMPTY) String checksum, @ApiParam(value = "The output port id.", required = true) @PathParam("portId") String portId, @ApiParam(value = "The transaction id.", required = true) @PathParam("transactionId") String transactionId, @Context HttpServletRequest req, @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("commitOutputPortTransaction request: portId={}, transactionId={}", portId, transactionId);
final int transportProtocolVersion = validationResult.transportProtocolVersion;
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final Peer peer = constructPeer(req, inputStream, out, portId, transactionId);
final TransactionResultEntity entity = new TransactionResultEntity();
try {
HttpFlowFileServerProtocol serverProtocol = initiateServerProtocol(req, peer, transportProtocolVersion);
String inputErrMessage = null;
if (responseCode == null) {
inputErrMessage = "responseCode is required.";
} else if (ResponseCode.CONFIRM_TRANSACTION.getCode() != responseCode && ResponseCode.CANCEL_TRANSACTION.getCode() != responseCode) {
inputErrMessage = "responseCode " + responseCode + " is invalid. ";
}
if (inputErrMessage != null) {
entity.setMessage(inputErrMessage);
entity.setResponseCode(ResponseCode.ABORT.getCode());
return Response.status(Response.Status.BAD_REQUEST).entity(entity).build();
}
if (ResponseCode.CANCEL_TRANSACTION.getCode() == responseCode) {
return cancelTransaction(transactionId, entity);
}
int flowFileSent = serverProtocol.commitTransferTransaction(peer, checksum);
entity.setResponseCode(ResponseCode.CONFIRM_TRANSACTION.getCode());
entity.setFlowFileSent(flowFileSent);
} catch (HandshakeException e) {
return responseCreator.handshakeExceptionResponse(e);
} catch (Exception e) {
HttpServerCommunicationsSession commsSession = (HttpServerCommunicationsSession) peer.getCommunicationsSession();
logger.error("Failed to process the request", e);
if (ResponseCode.BAD_CHECKSUM.equals(commsSession.getResponseCode())) {
entity.setResponseCode(commsSession.getResponseCode().getCode());
entity.setMessage(e.getMessage());
Response.ResponseBuilder builder = Response.status(Response.Status.BAD_REQUEST).entity(entity);
return noCache(builder).build();
}
return responseCreator.unexpectedErrorResponse(portId, transactionId, e);
}
return noCache(setCommonHeaders(Response.ok(entity), transportProtocolVersion, transactionManager)).build();
}
Aggregations