Search in sources :

Example 1 with HttpCommunicationsSession

use of org.apache.nifi.remote.io.http.HttpCommunicationsSession in project nifi by apache.

the class TestStandardRemoteGroupPort method testSendHttp.

@Test
public void testSendHttp() throws Exception {
    setupMock(SiteToSiteTransportProtocol.HTTP, TransferDirection.SEND);
    setupMockProcessSession();
    final String peerUrl = "https://node1.example.com:8080/nifi";
    final PeerDescription peerDescription = new PeerDescription("node1.example.com", 8080, true);
    final HttpCommunicationsSession commsSession = new HttpCommunicationsSession();
    commsSession.setUserDn("nifi.node1.example.com");
    final Peer peer = new Peer(peerDescription, commsSession, peerUrl, REMOTE_CLUSTER_URL);
    final String flowFileEndpointUri = "https://node1.example.com:8080/nifi-api/output-ports/port-id/transactions/transaction-id/flow-files";
    doReturn(peer).when(transaction).getCommunicant();
    commsSession.setDataTransferUrl(flowFileEndpointUri);
    final MockFlowFile flowFile = processSession.createFlowFile("0123456789".getBytes());
    sessionState.getFlowFileQueue().offer(flowFile);
    port.onTrigger(processContext, processSession);
    // Assert provenance.
    final List<ProvenanceEventRecord> provenanceEvents = sessionState.getProvenanceEvents();
    assertEquals(1, provenanceEvents.size());
    final ProvenanceEventRecord provenanceEvent = provenanceEvents.get(0);
    assertEquals(ProvenanceEventType.SEND, provenanceEvent.getEventType());
    assertEquals(flowFileEndpointUri, provenanceEvent.getTransitUri());
    assertEquals("Remote DN=nifi.node1.example.com", provenanceEvent.getDetails());
}
Also used : MockFlowFile(org.apache.nifi.util.MockFlowFile) HttpCommunicationsSession(org.apache.nifi.remote.io.http.HttpCommunicationsSession) ProvenanceEventRecord(org.apache.nifi.provenance.ProvenanceEventRecord) Test(org.junit.Test)

Example 2 with HttpCommunicationsSession

use of org.apache.nifi.remote.io.http.HttpCommunicationsSession in project nifi by apache.

the class HttpClient method createTransaction.

@Override
public Transaction createTransaction(final TransferDirection direction) throws HandshakeException, PortNotRunningException, ProtocolException, UnknownPortException, IOException {
    final int timeoutMillis = (int) config.getTimeout(TimeUnit.MILLISECONDS);
    PeerStatus peerStatus;
    while ((peerStatus = peerSelector.getNextPeerStatus(direction)) != null) {
        logger.debug("peerStatus={}", peerStatus);
        final CommunicationsSession commSession = new HttpCommunicationsSession();
        final String nodeApiUrl = resolveNodeApiUrl(peerStatus.getPeerDescription());
        final StringBuilder clusterUrls = new StringBuilder();
        config.getUrls().forEach(url -> {
            if (clusterUrls.length() > 0) {
                clusterUrls.append(",");
                clusterUrls.append(url);
            }
        });
        final Peer peer = new Peer(peerStatus.getPeerDescription(), commSession, nodeApiUrl, clusterUrls.toString());
        final int penaltyMillis = (int) config.getPenalizationPeriod(TimeUnit.MILLISECONDS);
        String portId = config.getPortIdentifier();
        if (StringUtils.isEmpty(portId)) {
            portId = siteInfoProvider.getPortIdentifier(config.getPortName(), direction);
            if (StringUtils.isEmpty(portId)) {
                peer.close();
                throw new IOException("Failed to determine the identifier of port " + config.getPortName());
            }
        }
        final SiteToSiteRestApiClient apiClient = new SiteToSiteRestApiClient(config.getSslContext(), config.getHttpProxy(), config.getEventReporter());
        apiClient.setBaseUrl(peer.getUrl());
        apiClient.setConnectTimeoutMillis(timeoutMillis);
        apiClient.setReadTimeoutMillis(timeoutMillis);
        apiClient.setCacheExpirationMillis(config.getCacheExpiration(TimeUnit.MILLISECONDS));
        apiClient.setLocalAddress(config.getLocalAddress());
        apiClient.setCompress(config.isUseCompression());
        apiClient.setRequestExpirationMillis(config.getIdleConnectionExpiration(TimeUnit.MILLISECONDS));
        apiClient.setBatchCount(config.getPreferredBatchCount());
        apiClient.setBatchSize(config.getPreferredBatchSize());
        apiClient.setBatchDurationMillis(config.getPreferredBatchDuration(TimeUnit.MILLISECONDS));
        final String transactionUrl;
        try {
            transactionUrl = apiClient.initiateTransaction(direction, portId);
            commSession.setUserDn(apiClient.getTrustedPeerDn());
        } catch (final Exception e) {
            apiClient.close();
            logger.warn("Penalizing a peer {} due to {}", peer, e.toString());
            peerSelector.penalize(peer, penaltyMillis);
            // Following exceptions will be thrown even if we tried other peers, so throw it.
            if (e instanceof UnknownPortException || e instanceof PortNotRunningException || e instanceof HandshakeException) {
                throw e;
            }
            logger.debug("Continue trying other peers...");
            continue;
        }
        // We found a valid peer to communicate with.
        final Integer transactionProtocolVersion = apiClient.getTransactionProtocolVersion();
        final HttpClientTransaction transaction = new HttpClientTransaction(transactionProtocolVersion, peer, direction, config.isUseCompression(), portId, penaltyMillis, config.getEventReporter()) {

            @Override
            protected void close() throws IOException {
                try {
                    super.close();
                } finally {
                    activeTransactions.remove(this);
                }
            }
        };
        try {
            transaction.initialize(apiClient, transactionUrl);
        } catch (final Exception e) {
            transaction.error();
            throw e;
        }
        activeTransactions.add(transaction);
        return transaction;
    }
    logger.info("Couldn't find a valid peer to communicate with.");
    return null;
}
Also used : HttpCommunicationsSession(org.apache.nifi.remote.io.http.HttpCommunicationsSession) Peer(org.apache.nifi.remote.Peer) SiteToSiteRestApiClient(org.apache.nifi.remote.util.SiteToSiteRestApiClient) UnknownPortException(org.apache.nifi.remote.exception.UnknownPortException) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) HttpCommunicationsSession(org.apache.nifi.remote.io.http.HttpCommunicationsSession) IOException(java.io.IOException) PortNotRunningException(org.apache.nifi.remote.exception.PortNotRunningException) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) UnknownPortException(org.apache.nifi.remote.exception.UnknownPortException) IOException(java.io.IOException) ProtocolException(org.apache.nifi.remote.exception.ProtocolException) PeerStatus(org.apache.nifi.remote.PeerStatus) PortNotRunningException(org.apache.nifi.remote.exception.PortNotRunningException) HandshakeException(org.apache.nifi.remote.exception.HandshakeException) HttpClientTransaction(org.apache.nifi.remote.protocol.http.HttpClientTransaction)

Example 3 with HttpCommunicationsSession

use of org.apache.nifi.remote.io.http.HttpCommunicationsSession in project nifi by apache.

the class HttpClientTransaction method writeTransactionResponse.

@Override
protected void writeTransactionResponse(ResponseCode response, String explanation) throws IOException {
    HttpCommunicationsSession commSession = (HttpCommunicationsSession) peer.getCommunicationsSession();
    if (TransferDirection.RECEIVE.equals(direction)) {
        switch(response) {
            case CONFIRM_TRANSACTION:
                logger.debug("{} Confirming transaction. checksum={}", this, explanation);
                commSession.setChecksum(explanation);
                break;
            case TRANSACTION_FINISHED:
                logger.debug("{} Finishing transaction.", this);
                break;
            case CANCEL_TRANSACTION:
                logger.debug("{} Canceling transaction. explanation={}", this, explanation);
                TransactionResultEntity resultEntity = apiClient.commitReceivingFlowFiles(transactionUrl, ResponseCode.CANCEL_TRANSACTION, null);
                ResponseCode cancelResponse = ResponseCode.fromCode(resultEntity.getResponseCode());
                switch(cancelResponse) {
                    case CANCEL_TRANSACTION:
                        logger.debug("{} CANCEL_TRANSACTION, The transaction is canceled on server properly.", this);
                        break;
                    default:
                        logger.warn("{} CANCEL_TRANSACTION, Expected the transaction is canceled on server, but received {}.", this, cancelResponse);
                        break;
                }
                break;
        }
    } else {
        switch(response) {
            case FINISH_TRANSACTION:
                // The actual HTTP request will be sent in readTransactionResponse.
                logger.debug("{} Finished sending flow files.", this);
                break;
            case BAD_CHECKSUM:
                {
                    TransactionResultEntity resultEntity = apiClient.commitTransferFlowFiles(transactionUrl, ResponseCode.BAD_CHECKSUM);
                    ResponseCode badChecksumCancelResponse = ResponseCode.fromCode(resultEntity.getResponseCode());
                    switch(badChecksumCancelResponse) {
                        case CANCEL_TRANSACTION:
                            logger.debug("{} BAD_CHECKSUM, The transaction is canceled on server properly.", this);
                            break;
                        default:
                            logger.warn("{} BAD_CHECKSUM, Expected the transaction is canceled on server, but received {}.", this, badChecksumCancelResponse);
                            break;
                    }
                }
                break;
            case CONFIRM_TRANSACTION:
                // The actual HTTP request will be sent in readTransactionResponse.
                logger.debug("{} Transaction is confirmed.", this);
                break;
            case CANCEL_TRANSACTION:
                {
                    logger.debug("{} Canceling transaction.", this);
                    TransactionResultEntity resultEntity = apiClient.commitTransferFlowFiles(transactionUrl, ResponseCode.CANCEL_TRANSACTION);
                    ResponseCode cancelResponse = ResponseCode.fromCode(resultEntity.getResponseCode());
                    switch(cancelResponse) {
                        case CANCEL_TRANSACTION:
                            logger.debug("{} CANCEL_TRANSACTION, The transaction is canceled on server properly.", this);
                            break;
                        default:
                            logger.warn("{} CANCEL_TRANSACTION, Expected the transaction is canceled on server, but received {}.", this, cancelResponse);
                            break;
                    }
                }
                break;
        }
    }
}
Also used : TransactionResultEntity(org.apache.nifi.web.api.entity.TransactionResultEntity) ResponseCode(org.apache.nifi.remote.protocol.ResponseCode) HttpCommunicationsSession(org.apache.nifi.remote.io.http.HttpCommunicationsSession)

Example 4 with HttpCommunicationsSession

use of org.apache.nifi.remote.io.http.HttpCommunicationsSession in project nifi by apache.

the class SiteToSiteRestApiClient method finishTransferFlowFiles.

public void finishTransferFlowFiles(final CommunicationsSession commSession) throws IOException {
    if (postResult == null) {
        new IllegalStateException("Data transfer has not started yet.");
    }
    // No more data can be sent.
    // Close PipedOutputStream so that dataPacketChannel doesn't blocked.
    // If we don't close this output stream, then PipedInputStream loops infinitely at read().
    commSession.getOutput().getOutputStream().close();
    logger.debug("{} FinishTransferFlowFiles no more data can be sent", this);
    try {
        if (!transferDataLatch.await(requestExpirationMillis, TimeUnit.MILLISECONDS)) {
            throw new IOException("Awaiting transferDataLatch has been timeout.");
        }
    } catch (final InterruptedException e) {
        throw new IOException("Awaiting transferDataLatch has been interrupted.", e);
    }
    stopExtendingTtl();
    final HttpResponse response;
    try {
        response = postResult.get(readTimeoutMillis, TimeUnit.MILLISECONDS);
    } catch (final ExecutionException e) {
        logger.debug("Something has happened at sending data thread. {}", e.getMessage());
        throw toIOException(e);
    } catch (TimeoutException | InterruptedException e) {
        throw new IOException(e);
    }
    final int responseCode = response.getStatusLine().getStatusCode();
    switch(responseCode) {
        case RESPONSE_CODE_ACCEPTED:
            final String receivedChecksum = EntityUtils.toString(response.getEntity());
            ((HttpInput) commSession.getInput()).setInputStream(new ByteArrayInputStream(receivedChecksum.getBytes()));
            ((HttpCommunicationsSession) commSession).setChecksum(receivedChecksum);
            logger.debug("receivedChecksum={}", receivedChecksum);
            break;
        default:
            try (InputStream content = response.getEntity().getContent()) {
                throw handleErrResponse(responseCode, content);
            }
    }
}
Also used : HttpCommunicationsSession(org.apache.nifi.remote.io.http.HttpCommunicationsSession) PipedInputStream(java.io.PipedInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) HttpResponse(org.apache.http.HttpResponse) CloseableHttpResponse(org.apache.http.client.methods.CloseableHttpResponse) IOException(java.io.IOException) HttpInput(org.apache.nifi.remote.io.http.HttpInput) ByteArrayInputStream(java.io.ByteArrayInputStream) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException)

Example 5 with HttpCommunicationsSession

use of org.apache.nifi.remote.io.http.HttpCommunicationsSession in project nifi by apache.

the class TestHttpClientTransaction method testSendTwoFlowFiles.

@Test
public void testSendTwoFlowFiles() throws IOException {
    SiteToSiteRestApiClient apiClient = mock(SiteToSiteRestApiClient.class);
    final String transactionUrl = "http://www.example.com/data-transfer/input-ports/portId/transactions/transactionId";
    doNothing().when(apiClient).openConnectionForSend(eq("portId"), any(Peer.class));
    // Emulate that server returns correct checksum.
    doAnswer(new Answer() {

        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            HttpCommunicationsSession commSession = (HttpCommunicationsSession) invocation.getArguments()[0];
            commSession.setChecksum("3359812065");
            return null;
        }
    }).when(apiClient).finishTransferFlowFiles(any(CommunicationsSession.class));
    TransactionResultEntity resultEntity = new TransactionResultEntity();
    resultEntity.setResponseCode(ResponseCode.TRANSACTION_FINISHED.getCode());
    doReturn(resultEntity).when(apiClient).commitTransferFlowFiles(eq(transactionUrl), eq(CONFIRM_TRANSACTION));
    ByteArrayOutputStream serverResponseBos = new ByteArrayOutputStream();
    ByteArrayInputStream serverResponse = new ByteArrayInputStream(serverResponseBos.toByteArray());
    ByteArrayOutputStream clientRequest = new ByteArrayOutputStream();
    HttpClientTransaction transaction = getClientTransaction(serverResponse, clientRequest, apiClient, TransferDirection.SEND, transactionUrl);
    execSendTwoFlowFiles(transaction);
    InputStream sentByClient = new ByteArrayInputStream(clientRequest.toByteArray());
    DataPacket packetByClient = codec.decode(sentByClient);
    assertEquals("contents on client 1", readContents(packetByClient));
    packetByClient = codec.decode(sentByClient);
    assertEquals("contents on client 2", readContents(packetByClient));
    assertEquals(-1, sentByClient.read());
    verify(apiClient).commitTransferFlowFiles(transactionUrl, CONFIRM_TRANSACTION);
}
Also used : TransactionResultEntity(org.apache.nifi.web.api.entity.TransactionResultEntity) HttpCommunicationsSession(org.apache.nifi.remote.io.http.HttpCommunicationsSession) ByteArrayInputStream(org.apache.nifi.stream.io.ByteArrayInputStream) InputStream(java.io.InputStream) SiteToSiteRestApiClient(org.apache.nifi.remote.util.SiteToSiteRestApiClient) Peer(org.apache.nifi.remote.Peer) CommunicationsSession(org.apache.nifi.remote.protocol.CommunicationsSession) HttpCommunicationsSession(org.apache.nifi.remote.io.http.HttpCommunicationsSession) ByteArrayOutputStream(org.apache.nifi.stream.io.ByteArrayOutputStream) DataPacket(org.apache.nifi.remote.protocol.DataPacket) SiteToSiteTestUtils.createDataPacket(org.apache.nifi.remote.protocol.SiteToSiteTestUtils.createDataPacket) Answer(org.mockito.stubbing.Answer) Mockito.doAnswer(org.mockito.Mockito.doAnswer) ByteArrayInputStream(org.apache.nifi.stream.io.ByteArrayInputStream) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Test(org.junit.Test)

Aggregations

HttpCommunicationsSession (org.apache.nifi.remote.io.http.HttpCommunicationsSession)15 InputStream (java.io.InputStream)6 Peer (org.apache.nifi.remote.Peer)6 CommunicationsSession (org.apache.nifi.remote.protocol.CommunicationsSession)6 DataPacket (org.apache.nifi.remote.protocol.DataPacket)6 TransactionResultEntity (org.apache.nifi.web.api.entity.TransactionResultEntity)6 Test (org.junit.Test)6 ByteArrayInputStream (org.apache.nifi.stream.io.ByteArrayInputStream)5 ByteArrayOutputStream (org.apache.nifi.stream.io.ByteArrayOutputStream)5 SiteToSiteRestApiClient (org.apache.nifi.remote.util.SiteToSiteRestApiClient)4 ByteArrayInputStream (java.io.ByteArrayInputStream)3 IOException (java.io.IOException)3 PipedInputStream (java.io.PipedInputStream)3 ProvenanceEventRecord (org.apache.nifi.provenance.ProvenanceEventRecord)3 HttpInput (org.apache.nifi.remote.io.http.HttpInput)3 SiteToSiteTestUtils.createDataPacket (org.apache.nifi.remote.protocol.SiteToSiteTestUtils.createDataPacket)3 MockFlowFile (org.apache.nifi.util.MockFlowFile)3 Mockito.doAnswer (org.mockito.Mockito.doAnswer)3 InvocationOnMock (org.mockito.invocation.InvocationOnMock)3 Answer (org.mockito.stubbing.Answer)3