@Override public DownloadableContent getContent(final ContentRequestContext request) { // if clustered, send request to cluster manager if (properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) { // get the URI URI dataUri; try { dataUri = new URI(request.getDataUri()); } catch (final URISyntaxException use) { throw new ClusterRequestException(use); } // set the request parameters final MultivaluedMap<String, String> parameters = new MultivaluedMapImpl(); parameters.add(CLIENT_ID_PARAM, request.getClientId()); // set the headers final Map<String, String> headers = new HashMap<>(); if (StringUtils.isNotBlank(request.getProxiedEntitiesChain())) { headers.put("X-ProxiedEntitiesChain", request.getProxiedEntitiesChain()); } // add the user's authorities (if any) to the headers final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null) { final Object userDetailsObj = authentication.getPrincipal(); if (userDetailsObj instanceof NiFiUserDetails) { // serialize user details object final String hexEncodedUserDetails = WebUtils.serializeObjectToHex((Serializable) userDetailsObj); // put serialized user details in header headers.put("X-ProxiedEntityUserDetails", hexEncodedUserDetails); } } // ensure we were able to detect the cluster node id if (request.getClusterNodeId() == null) { throw new IllegalArgumentException("Unable to determine the which node has the content."); } // get the target node and ensure it exists final NodeIdentifier nodeId = clusterCoordinator.getNodeIdentifier(request.getClusterNodeId()); final Set<NodeIdentifier> targetNodes = Collections.singleton(nodeId); // replicate the request to the specific node NodeResponse nodeResponse; try { nodeResponse = requestReplicator .replicate(targetNodes, HttpMethod.GET, dataUri, parameters, headers) .awaitMergedResponse(); } catch (InterruptedException e) { throw new IllegalClusterStateException( "Interrupted while waiting for a response from node"); } final ClientResponse clientResponse = nodeResponse.getClientResponse(); final MultivaluedMap<String, String> responseHeaders = clientResponse.getHeaders(); // ensure an appropriate response if (Status.NOT_FOUND.getStatusCode() == clientResponse.getStatusInfo().getStatusCode()) { throw new ResourceNotFoundException(clientResponse.getEntity(String.class)); } else if (Status.FORBIDDEN.getStatusCode() == clientResponse.getStatusInfo().getStatusCode() || Status.UNAUTHORIZED.getStatusCode() == clientResponse.getStatusInfo().getStatusCode()) { throw new AccessDeniedException(clientResponse.getEntity(String.class)); } else if (Status.OK.getStatusCode() != clientResponse.getStatusInfo().getStatusCode()) { throw new IllegalStateException(clientResponse.getEntity(String.class)); } // get the file name final String contentDisposition = responseHeaders.getFirst("Content-Disposition"); final String filename = StringUtils.substringBetween(contentDisposition, "filename=\"", "\""); // get the content type final String contentType = responseHeaders.getFirst("Content-Type"); // create the downloadable content return new DownloadableContent(filename, contentType, clientResponse.getEntityInputStream()); } else { // example URIs: // http://localhost:8080/nifi-api/provenance/events/{id}/content/{input|output} // http://localhost:8080/nifi-api/flowfile-queues/{uuid}/flowfiles/{uuid}/content // get just the context path for comparison final String dataUri = StringUtils.substringAfter(request.getDataUri(), "/nifi-api"); if (StringUtils.isBlank(dataUri)) { throw new IllegalArgumentException("The specified data reference URI is not valid."); } // flowfile listing content final Matcher flowFileMatcher = FLOWFILE_CONTENT_URI_PATTERN.matcher(dataUri); if (flowFileMatcher.matches()) { final String connectionId = flowFileMatcher.group(1); final String flowfileId = flowFileMatcher.group(2); return getFlowFileContent(connectionId, flowfileId, dataUri); } // provenance event content final Matcher provenanceMatcher = PROVENANCE_CONTENT_URI_PATTERN.matcher(dataUri); if (provenanceMatcher.matches()) { try { final Long eventId = Long.parseLong(provenanceMatcher.group(1)); final ContentDirection direction = ContentDirection.valueOf(provenanceMatcher.group(2).toUpperCase()); return getProvenanceEventContent(eventId, dataUri, direction); } catch (final IllegalArgumentException iae) { throw new IllegalArgumentException("The specified data reference URI is not valid."); } } // invalid uri throw new IllegalArgumentException("The specified data reference URI is not valid."); } }
/** * Gets the system diagnostics for this NiFi instance. * * @return A systemDiagnosticsEntity. * @throws InterruptedException if interrupted */ @GET @Consumes(MediaType.WILDCARD) @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Gets the diagnostics for the system NiFi is running on", response = SystemDiagnosticsEntity.class, authorizations = {@Authorization(value = "Read - /system", type = "")}) @ApiResponses( value = { @ApiResponse(code = 401, message = "Client could not be authenticated."), @ApiResponse(code = 403, message = "Client is not authorized to make this request."), }) public Response getSystemDiagnostics( @ApiParam( value = "Whether or not to include the breakdown per node. Optional, defaults to false", required = false) @QueryParam("nodewise") @DefaultValue(NODEWISE) final Boolean nodewise, @ApiParam(value = "The id of the node where to get the status.", required = false) @QueryParam("clusterNodeId") final String clusterNodeId) throws InterruptedException { authorizeSystem(); // ensure a valid request if (Boolean.TRUE.equals(nodewise) && clusterNodeId != null) { throw new IllegalArgumentException( "Nodewise requests cannot be directed at a specific node."); } if (isReplicateRequest()) { // determine where this request should be sent if (clusterNodeId == null) { final NodeResponse nodeResponse; // Determine whether we should replicate only to the cluster coordinator, or if we should // replicate directly // to the cluster nodes themselves. if (getReplicationTarget() == ReplicationTarget.CLUSTER_NODES) { nodeResponse = getRequestReplicator() .replicate( HttpMethod.GET, getAbsolutePath(), getRequestParameters(), getHeaders()) .awaitMergedResponse(); } else { nodeResponse = getRequestReplicator() .forwardToCoordinator( getClusterCoordinatorNode(), HttpMethod.GET, getAbsolutePath(), getRequestParameters(), getHeaders()) .awaitMergedResponse(); } final SystemDiagnosticsEntity entity = (SystemDiagnosticsEntity) nodeResponse.getUpdatedEntity(); // ensure there is an updated entity (result of merging) and prune the response as necessary if (entity != null && !nodewise) { entity.getSystemDiagnostics().setNodeSnapshots(null); } return nodeResponse.getResponse(); } else { return replicate(HttpMethod.GET); } } final SystemDiagnosticsDTO systemDiagnosticsDto = serviceFacade.getSystemDiagnostics(); // create the response final SystemDiagnosticsEntity entity = new SystemDiagnosticsEntity(); entity.setSystemDiagnostics(systemDiagnosticsDto); // generate the response return clusterContext(generateOkResponse(entity)).build(); }
@Override @PreAuthorize("hasRole('ROLE_PROVENANCE')") public DownloadableContent getContent(final ContentRequestContext request) { // if clustered, send request to cluster manager if (properties.isClusterManager()) { // get the URI URI dataUri; try { dataUri = new URI(request.getDataUri()); } catch (final URISyntaxException use) { throw new ClusterRequestException(use); } // set the request parameters final MultivaluedMap<String, String> parameters = new MultivaluedMapImpl(); parameters.add(CLIENT_ID_PARAM, request.getClientId()); // set the headers final Map<String, String> headers = new HashMap<>(); if (StringUtils.isNotBlank(request.getProxiedEntitiesChain())) { headers.put("X-ProxiedEntitiesChain", request.getProxiedEntitiesChain()); } // add the user's authorities (if any) to the headers final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null) { final Object userDetailsObj = authentication.getPrincipal(); if (userDetailsObj instanceof NiFiUserDetails) { // serialize user details object final String hexEncodedUserDetails = WebUtils.serializeObjectToHex((Serializable) userDetailsObj); // put serialized user details in header headers.put("X-ProxiedEntityUserDetails", hexEncodedUserDetails); } } // get the target node and ensure it exists final Node targetNode = clusterManager.getNode(request.getClusterNodeId()); if (targetNode == null) { throw new UnknownNodeException("The specified cluster node does not exist."); } final Set<NodeIdentifier> targetNodes = new HashSet<>(); targetNodes.add(targetNode.getNodeId()); // replicate the request to the specific node final NodeResponse nodeResponse = clusterManager.applyRequest(HttpMethod.GET, dataUri, parameters, headers, targetNodes); final ClientResponse clientResponse = nodeResponse.getClientResponse(); final MultivaluedMap<String, String> responseHeaders = clientResponse.getHeaders(); // get the file name final String contentDisposition = responseHeaders.getFirst("Content-Disposition"); final String filename = StringUtils.substringBetween(contentDisposition, "filename=\"", "\""); // get the content type final String contentType = responseHeaders.getFirst("Content-Type"); // create the downloadable content return new DownloadableContent(filename, contentType, clientResponse.getEntityInputStream()); } else { // example URI: http://localhost:8080/nifi-api/controller/provenance/events/1/content/input final String eventDetails = StringUtils.substringAfterLast(request.getDataUri(), "events/"); final String rawEventId = StringUtils.substringBefore(eventDetails, "/content/"); final String rawDirection = StringUtils.substringAfterLast(eventDetails, "/content/"); // get the content type final Long eventId; final ContentDirection direction; try { eventId = Long.parseLong(rawEventId); direction = ContentDirection.valueOf(rawDirection.toUpperCase()); } catch (final IllegalArgumentException iae) { throw new IllegalArgumentException("The specified data reference URI is not valid."); } return serviceFacade.getContent(eventId, request.getDataUri(), direction); } }