Search in sources :

Example 76 with StreamResponse

use of com.linkedin.r2.message.stream.StreamResponse in project rest.li by linkedin.

the class AbstractAsyncR2StreamServlet method service.

@Override
public void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
    final AsyncContext ctx = req.startAsync(req, resp);
    ctx.setTimeout(_timeout);
    final WrappedAsyncContext wrappedCtx = new WrappedAsyncContext(ctx);
    final AsyncEventIOHandler ioHandler = new AsyncEventIOHandler(req.getInputStream(), resp.getOutputStream(), wrappedCtx, MAX_BUFFERED_CHUNKS);
    final RequestContext requestContext = ServletHelper.readRequestContext(req);
    final StreamRequest streamRequest;
    try {
        streamRequest = ServletHelper.readFromServletRequest(req, ioHandler);
    } catch (URISyntaxException e) {
        ServletHelper.writeToServletError(resp, RestStatus.BAD_REQUEST, e.toString());
        wrappedCtx.complete();
        return;
    }
    final AtomicBoolean startedResponding = new AtomicBoolean(false);
    ctx.addListener(new AsyncListener() {

        @Override
        public void onTimeout(AsyncEvent event) throws IOException {
            LOG.error("Server timeout for request: " + formatURI(req.getRequestURI()));
            if (startedResponding.compareAndSet(false, true)) {
                LOG.info("Returning server timeout response");
                ServletHelper.writeToServletError(resp, RestStatus.INTERNAL_SERVER_ERROR, "Server timeout");
            } else {
                req.setAttribute(ASYNC_IOEXCEPTION, new ServletException("Server timeout"));
            }
            ioHandler.exitLoop();
            wrappedCtx.complete();
        }

        @Override
        public void onStartAsync(AsyncEvent event) throws IOException {
        // Nothing to do here
        }

        @Override
        public void onError(AsyncEvent event) throws IOException {
            LOG.error("Server error for request: " + formatURI(req.getRequestURI()));
            if (startedResponding.compareAndSet(false, true)) {
                LOG.info("Returning server error response");
                ServletHelper.writeToServletError(resp, RestStatus.INTERNAL_SERVER_ERROR, "Server error");
            } else {
                req.setAttribute(ASYNC_IOEXCEPTION, new ServletException("Server error"));
            }
            ioHandler.exitLoop();
            wrappedCtx.complete();
        }

        @Override
        public void onComplete(AsyncEvent event) throws IOException {
            Object exception = req.getAttribute(ASYNC_IOEXCEPTION);
            if (exception != null) {
                throw new IOException((Throwable) exception);
            }
        }
    });
    final TransportCallback<StreamResponse> callback = new TransportCallback<StreamResponse>() {

        @Override
        public void onResponse(final TransportResponse<StreamResponse> response) {
            if (startedResponding.compareAndSet(false, true)) {
                ctx.start(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            StreamResponse streamResponse = ServletHelper.writeResponseHeadersToServletResponse(response, resp);
                            streamResponse.getEntityStream().setReader(ioHandler);
                            ioHandler.loop();
                        } catch (Exception e) {
                            req.setAttribute(ASYNC_IOEXCEPTION, e);
                            wrappedCtx.complete();
                        }
                    }
                });
            } else {
                LOG.error("Dropped a response; this is mostly like because that AsyncContext timeout or error had already happened");
            }
        }
    };
    // we have to use a new thread and let this thread return to pool. otherwise the timeout won't start
    ctx.start(new Runnable() {

        @Override
        public void run() {
            try {
                getDispatcher().handleRequest(streamRequest, requestContext, callback);
                ioHandler.loop();
            } catch (Exception e) {
                req.setAttribute(ASYNC_IOEXCEPTION, e);
                wrappedCtx.complete();
            }
        }
    });
}
Also used : TransportCallback(com.linkedin.r2.transport.common.bridge.common.TransportCallback) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) AsyncContext(javax.servlet.AsyncContext) URISyntaxException(java.net.URISyntaxException) IOException(java.io.IOException) AsyncEvent(javax.servlet.AsyncEvent) TransportResponse(com.linkedin.r2.transport.common.bridge.common.TransportResponse) ServletException(javax.servlet.ServletException) URISyntaxException(java.net.URISyntaxException) IOException(java.io.IOException) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) ServletException(javax.servlet.ServletException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AsyncListener(javax.servlet.AsyncListener) RequestContext(com.linkedin.r2.message.RequestContext)

Example 77 with StreamResponse

use of com.linkedin.r2.message.stream.StreamResponse in project rest.li by linkedin.

the class AbstractR2StreamServlet method service.

@Override
protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
    final SyncIOHandler ioHandler = new SyncIOHandler(req.getInputStream(), resp.getOutputStream(), 2, _ioHandlerTimeout);
    RequestContext requestContext = ServletHelper.readRequestContext(req);
    StreamRequest streamRequest;
    try {
        streamRequest = ServletHelper.readFromServletRequest(req, ioHandler);
    } catch (URISyntaxException e) {
        ServletHelper.writeToServletError(resp, RestStatus.BAD_REQUEST, e.toString());
        return;
    }
    TransportCallback<StreamResponse> callback = new TransportCallback<StreamResponse>() {

        @Override
        public void onResponse(TransportResponse<StreamResponse> response) {
            StreamResponse streamResponse = ServletHelper.writeResponseHeadersToServletResponse(response, resp);
            streamResponse.getEntityStream().setReader(ioHandler);
        }
    };
    getDispatcher().handleRequest(streamRequest, requestContext, callback);
    ioHandler.loop();
}
Also used : TransportCallback(com.linkedin.r2.transport.common.bridge.common.TransportCallback) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) RequestContext(com.linkedin.r2.message.RequestContext) URISyntaxException(java.net.URISyntaxException) TransportResponse(com.linkedin.r2.transport.common.bridge.common.TransportResponse) StreamRequest(com.linkedin.r2.message.stream.StreamRequest)

Example 78 with StreamResponse

use of com.linkedin.r2.message.stream.StreamResponse in project rest.li by linkedin.

the class TestMIMEIntegrationReaderDrain method executeRequestWithDrainStrategy.

///////////////////////////////////////////////////////////////////////////////////////
private MimeMultipart executeRequestWithDrainStrategy(final int chunkSize, final List<MimeBodyPart> bodyPartList, final String drainStrategy, final String serverHeaderPrefix) throws Exception {
    MimeMultipart multiPartMimeBody = new MimeMultipart();
    //Add your body parts
    for (final MimeBodyPart bodyPart : bodyPartList) {
        multiPartMimeBody.addBodyPart(bodyPart);
    }
    final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    multiPartMimeBody.writeTo(byteArrayOutputStream);
    final ByteString requestPayload = ByteString.copy(byteArrayOutputStream.toByteArray());
    final VariableByteStringWriter variableByteStringWriter = new VariableByteStringWriter(requestPayload, chunkSize);
    final EntityStream entityStream = EntityStreams.newEntityStream(variableByteStringWriter);
    final StreamRequestBuilder builder = new StreamRequestBuilder(Bootstrap.createHttpURI(PORT, SERVER_URI));
    StreamRequest request = builder.setMethod("POST").setHeader(HEADER_CONTENT_TYPE, multiPartMimeBody.getContentType()).setHeader(DRAIN_HEADER, drainStrategy).build(entityStream);
    final AtomicInteger status = new AtomicInteger(-1);
    final CountDownLatch latch = new CountDownLatch(1);
    final Map<String, String> responseHeaders = new HashMap<String, String>();
    Callback<StreamResponse> callback = expectSuccessCallback(latch, status, responseHeaders);
    _client.streamRequest(request, callback);
    latch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
    Assert.assertEquals(status.get(), RestStatus.OK);
    Assert.assertEquals(responseHeaders.get(DRAIN_HEADER), serverHeaderPrefix + drainStrategy);
    return multiPartMimeBody;
}
Also used : VariableByteStringWriter(com.linkedin.multipart.utils.VariableByteStringWriter) HashMap(java.util.HashMap) ByteString(com.linkedin.data.ByteString) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ByteString(com.linkedin.data.ByteString) CountDownLatch(java.util.concurrent.CountDownLatch) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) EntityStream(com.linkedin.r2.message.stream.entitystream.EntityStream) MimeMultipart(javax.mail.internet.MimeMultipart) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) MimeBodyPart(javax.mail.internet.MimeBodyPart)

Example 79 with StreamResponse

use of com.linkedin.r2.message.stream.StreamResponse in project rest.li by linkedin.

the class TestMIMEIntegrationReaderWriter method executeRequestAndAssert.

///////////////////////////////////////////////////////////////////////////////////////
//This method will execute a StreamRequest using a payload comprised of the provided MultiPartMIMEWriter. The request
//makes its way to a server which will read all the parts one by one and store them in a list. Subsequently,
//an assertion is performed to make sure that each part was read and saved properly on the server.
private void executeRequestAndAssert(final MultiPartMIMEWriter requestWriter, final List<MIMEDataPart> expectedParts) throws Exception {
    final StreamRequest streamRequest = MultiPartMIMEStreamRequestFactory.generateMultiPartMIMEStreamRequest(Bootstrap.createHttpURI(PORT, SERVER_URI), "mixed", requestWriter, Collections.<String, String>emptyMap());
    final AtomicInteger status = new AtomicInteger(-1);
    final CountDownLatch latch = new CountDownLatch(1);
    Callback<StreamResponse> callback = expectSuccessCallback(latch, status, new HashMap<String, String>());
    _client.streamRequest(streamRequest, callback);
    latch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
    Assert.assertEquals(status.get(), RestStatus.OK);
    List<SinglePartMIMEReaderCallbackImpl> singlePartMIMEReaderCallbacks = _mimeServerRequestHandler.getTestMultiPartMIMEReaderCallback().getSinglePartMIMEReaderCallbacks();
    _mimeServerRequestHandler.getTestMultiPartMIMEReaderCallback().getSinglePartMIMEReaderCallbacks();
    Assert.assertEquals(singlePartMIMEReaderCallbacks.size(), expectedParts.size());
    for (int i = 0; i < singlePartMIMEReaderCallbacks.size(); i++) {
        //Actual
        final SinglePartMIMEReaderCallbackImpl currentCallback = singlePartMIMEReaderCallbacks.get(i);
        //Expected
        final MIMEDataPart currentExpectedPart = expectedParts.get(i);
        Assert.assertEquals(currentCallback.getHeaders(), currentExpectedPart.getPartHeaders());
        Assert.assertEquals(currentCallback.getFinishedData(), currentExpectedPart.getPartData());
    }
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) MIMEDataPart(com.linkedin.multipart.utils.MIMEDataPart) ByteString(com.linkedin.data.ByteString) CountDownLatch(java.util.concurrent.CountDownLatch) StreamRequest(com.linkedin.r2.message.stream.StreamRequest)

Example 80 with StreamResponse

use of com.linkedin.r2.message.stream.StreamResponse in project rest.li by linkedin.

the class TestMIMEChainingReader method testMimeReaderDataSource.

//Verifies that a multi part mime reader can be used as a data source to the writer.
//To make the test easier to write, we simply chain back to the client in the form of simulating a response.
@Test(dataProvider = "chunkSizes")
public void testMimeReaderDataSource(final int chunkSize) throws Exception {
    final List<MultiPartMIMEDataSourceWriter> dataSources = generateInputStreamDataSources(chunkSize, _scheduledExecutorService);
    final MultiPartMIMEWriter writer = new MultiPartMIMEWriter.Builder().appendDataSources(dataSources).build();
    final StreamRequest streamRequest = mock(StreamRequest.class);
    when(streamRequest.getEntityStream()).thenReturn(writer.getEntityStream());
    final String contentTypeHeader = "multipart/mixed; boundary=" + writer.getBoundary();
    when(streamRequest.getHeader(MultiPartMIMEUtils.CONTENT_TYPE_HEADER)).thenReturn(contentTypeHeader);
    //Client side preparation to read the part back on the callback
    //Note the chunks size will carry over since the client is controlling how much data he gets back
    //based on the chunk size he writes.
    final CountDownLatch latch = new CountDownLatch(1);
    ClientMultiPartMIMEReaderReceiverCallback _clientReceiver = new ClientMultiPartMIMEReaderReceiverCallback(latch);
    Callback<StreamResponse> callback = generateSuccessChainCallback(_clientReceiver);
    //Server side start
    MultiPartMIMEReader reader = MultiPartMIMEReader.createAndAcquireStream(streamRequest);
    ServerMultiPartMIMEChainReaderWriterCallback _serverSender = new ServerMultiPartMIMEChainReaderWriterCallback(callback, reader);
    reader.registerReaderCallback(_serverSender);
    latch.await(_testTimeout, TimeUnit.MILLISECONDS);
    //Verify client. No need to verify the server.
    List<MIMETestUtils.SinglePartMIMEFullReaderCallback> singlePartMIMEReaderCallbacks = _clientReceiver.getSinglePartMIMEReaderCallbacks();
    Assert.assertEquals(singlePartMIMEReaderCallbacks.size(), 4);
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(0).getFinishedData(), BODY_A.getPartData());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(0).getHeaders(), BODY_A.getPartHeaders());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(1).getFinishedData(), BODY_B.getPartData());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(1).getHeaders(), BODY_B.getPartHeaders());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(2).getFinishedData(), BODY_C.getPartData());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(2).getHeaders(), BODY_C.getPartHeaders());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(3).getFinishedData(), BODY_D.getPartData());
    Assert.assertEquals(singlePartMIMEReaderCallbacks.get(3).getHeaders(), BODY_D.getPartHeaders());
}
Also used : StreamResponse(com.linkedin.r2.message.stream.StreamResponse) CountDownLatch(java.util.concurrent.CountDownLatch) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) Test(org.testng.annotations.Test)

Aggregations

StreamResponse (com.linkedin.r2.message.stream.StreamResponse)104 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)71 Test (org.testng.annotations.Test)68 RequestContext (com.linkedin.r2.message.RequestContext)59 StreamRequestBuilder (com.linkedin.r2.message.stream.StreamRequestBuilder)53 ByteString (com.linkedin.data.ByteString)43 URI (java.net.URI)42 Callback (com.linkedin.common.callback.Callback)36 RestRequest (com.linkedin.r2.message.rest.RestRequest)33 CountDownLatch (java.util.concurrent.CountDownLatch)31 RestResponse (com.linkedin.r2.message.rest.RestResponse)28 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)27 StreamException (com.linkedin.r2.message.stream.StreamException)25 HashMap (java.util.HashMap)24 FutureCallback (com.linkedin.common.callback.FutureCallback)22 Map (java.util.Map)20 SinglePartMIMEFullReaderCallback (com.linkedin.multipart.utils.MIMETestUtils.SinglePartMIMEFullReaderCallback)17 StreamResponseBuilder (com.linkedin.r2.message.stream.StreamResponseBuilder)17 TransportCallback (com.linkedin.r2.transport.common.bridge.common.TransportCallback)17 MultiPartMIMEFullReaderCallback (com.linkedin.multipart.utils.MIMETestUtils.MultiPartMIMEFullReaderCallback)16