use of org.apache.nifi.remote.exception.BadRequestException in project nifi by apache.
the class SiteToSiteResource method getPeers.
/**
* Returns the available Peers and its status of this NiFi.
*
* @return A peersEntity.
*/
@GET
@Path("/peers")
@Consumes(MediaType.WILDCARD)
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@ApiOperation(value = "Returns the available Peers and its status of this NiFi", response = PeersEntity.class, authorizations = { @Authorization(value = "Read - /site-to-site") })
@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 = 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.") })
public Response getPeers(@Context HttpServletRequest req) {
authorizeSiteToSite();
if (!properties.isSiteToSiteHttpEnabled()) {
return responseCreator.httpSiteToSiteIsNotEnabledResponse();
}
final Integer transportProtocolVersion;
try {
transportProtocolVersion = negotiateTransportProtocolVersion(req, transportProtocolVersionNegotiator);
} catch (BadRequestException e) {
return responseCreator.badRequestResponse(e);
}
final List<PeerDTO> peers = new ArrayList<>();
if (properties.isNode()) {
try {
final Map<NodeIdentifier, NodeWorkload> clusterWorkload = clusterCoordinator.getClusterWorkload();
clusterWorkload.entrySet().stream().forEach(entry -> {
final PeerDTO peer = new PeerDTO();
final NodeIdentifier nodeId = entry.getKey();
final String siteToSiteAddress = nodeId.getSiteToSiteAddress();
peer.setHostname(siteToSiteAddress == null ? nodeId.getApiAddress() : siteToSiteAddress);
peer.setPort(nodeId.getSiteToSiteHttpApiPort() == null ? nodeId.getApiPort() : nodeId.getSiteToSiteHttpApiPort());
peer.setSecure(nodeId.isSiteToSiteSecure());
peer.setFlowFileCount(entry.getValue().getFlowFileCount());
peers.add(peer);
});
} catch (IOException e) {
throw new RuntimeException("Failed to retrieve cluster workload due to " + e, e);
}
} else {
// Standalone mode.
final PeerDTO peer = new PeerDTO();
// Private IP address or hostname may not be accessible from client in some environments.
// So, use the value defined in nifi.properties instead when it is defined.
final String remoteInputHost = properties.getRemoteInputHost();
String localName;
try {
// Get local host name using InetAddress if available, same as RAW socket does.
localName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to get local host name using InetAddress.", e);
}
localName = req.getLocalName();
}
peer.setHostname(isEmpty(remoteInputHost) ? localName : remoteInputHost);
peer.setPort(properties.getRemoteInputHttpPort());
peer.setSecure(properties.isSiteToSiteSecure());
// doesn't matter how many FlowFiles we have, because we're the only host.
peer.setFlowFileCount(0);
peers.add(peer);
}
final PeersEntity entity = new PeersEntity();
entity.setPeers(peers);
return noCache(setCommonHeaders(Response.ok(entity), transportProtocolVersion, transactionManager)).build();
}
use of org.apache.nifi.remote.exception.BadRequestException 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.BadRequestException 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.BadRequestException 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.BadRequestException 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));
}
Aggregations