Search in sources :

Example 1 with GenericFutureListener

use of io.netty.util.concurrent.GenericFutureListener in project jersey by jersey.

the class NettyConnector method apply.

@Override
public Future<?> apply(final ClientRequest jerseyRequest, final AsyncConnectorCallback jerseyCallback) {
    final CompletableFuture<Object> settableFuture = new CompletableFuture<>();
    final URI requestUri = jerseyRequest.getUri();
    String host = requestUri.getHost();
    int port = requestUri.getPort() != -1 ? requestUri.getPort() : "https".equals(requestUri.getScheme()) ? 443 : 80;
    try {
        Bootstrap b = new Bootstrap();
        b.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {

            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline p = ch.pipeline();
                // Enable HTTPS if necessary.
                if ("https".equals(requestUri.getScheme())) {
                    // making client authentication optional for now; it could be extracted to configurable property
                    JdkSslContext jdkSslContext = new JdkSslContext(client.getSslContext(), true, ClientAuth.NONE);
                    p.addLast(jdkSslContext.newHandler(ch.alloc()));
                }
                // http proxy
                Configuration config = jerseyRequest.getConfiguration();
                final Object proxyUri = config.getProperties().get(ClientProperties.PROXY_URI);
                if (proxyUri != null) {
                    final URI u = getProxyUri(proxyUri);
                    final String userName = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_USERNAME, String.class);
                    final String password = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class);
                    p.addLast(new HttpProxyHandler(new InetSocketAddress(u.getHost(), u.getPort() == -1 ? 8080 : u.getPort()), userName, password));
                }
                p.addLast(new HttpClientCodec());
                p.addLast(new ChunkedWriteHandler());
                p.addLast(new HttpContentDecompressor());
                p.addLast(new JerseyClientHandler(NettyConnector.this, jerseyRequest, jerseyCallback, settableFuture));
            }
        });
        // connect timeout
        Integer connectTimeout = ClientProperties.getValue(jerseyRequest.getConfiguration().getProperties(), ClientProperties.CONNECT_TIMEOUT, 0);
        if (connectTimeout > 0) {
            b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout);
        }
        // Make the connection attempt.
        final Channel ch = b.connect(host, port).sync().channel();
        // guard against prematurely closed channel
        final GenericFutureListener<io.netty.util.concurrent.Future<? super Void>> closeListener = new GenericFutureListener<io.netty.util.concurrent.Future<? super Void>>() {

            @Override
            public void operationComplete(io.netty.util.concurrent.Future<? super Void> future) throws Exception {
                if (!settableFuture.isDone()) {
                    settableFuture.completeExceptionally(new IOException("Channel closed."));
                }
            }
        };
        ch.closeFuture().addListener(closeListener);
        HttpRequest nettyRequest;
        if (jerseyRequest.hasEntity()) {
            nettyRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(jerseyRequest.getMethod()), requestUri.getRawPath());
        } else {
            nettyRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.valueOf(jerseyRequest.getMethod()), requestUri.getRawPath());
        }
        // headers
        for (final Map.Entry<String, List<String>> e : jerseyRequest.getStringHeaders().entrySet()) {
            nettyRequest.headers().add(e.getKey(), e.getValue());
        }
        // host header - http 1.1
        nettyRequest.headers().add(HttpHeaderNames.HOST, jerseyRequest.getUri().getHost());
        if (jerseyRequest.hasEntity()) {
            if (jerseyRequest.getLengthLong() == -1) {
                HttpUtil.setTransferEncodingChunked(nettyRequest, true);
            } else {
                nettyRequest.headers().add(HttpHeaderNames.CONTENT_LENGTH, jerseyRequest.getLengthLong());
            }
        }
        if (jerseyRequest.hasEntity()) {
            // Send the HTTP request.
            ch.writeAndFlush(nettyRequest);
            final JerseyChunkedInput jerseyChunkedInput = new JerseyChunkedInput(ch);
            jerseyRequest.setStreamProvider(new OutboundMessageContext.StreamProvider() {

                @Override
                public OutputStream getOutputStream(int contentLength) throws IOException {
                    return jerseyChunkedInput;
                }
            });
            if (HttpUtil.isTransferEncodingChunked(nettyRequest)) {
                ch.write(new HttpChunkedInput(jerseyChunkedInput));
            } else {
                ch.write(jerseyChunkedInput);
            }
            executorService.execute(new Runnable() {

                @Override
                public void run() {
                    // close listener is not needed any more.
                    ch.closeFuture().removeListener(closeListener);
                    try {
                        jerseyRequest.writeEntity();
                    } catch (IOException e) {
                        jerseyCallback.failure(e);
                        settableFuture.completeExceptionally(e);
                    }
                }
            });
            ch.flush();
        } else {
            // close listener is not needed any more.
            ch.closeFuture().removeListener(closeListener);
            // Send the HTTP request.
            ch.writeAndFlush(nettyRequest);
        }
    } catch (InterruptedException e) {
        settableFuture.completeExceptionally(e);
        return settableFuture;
    }
    return settableFuture;
}
Also used : NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) SocketChannel(io.netty.channel.socket.SocketChannel) Configuration(javax.ws.rs.core.Configuration) InetSocketAddress(java.net.InetSocketAddress) OutputStream(java.io.OutputStream) HttpClientCodec(io.netty.handler.codec.http.HttpClientCodec) URI(java.net.URI) OutboundMessageContext(org.glassfish.jersey.message.internal.OutboundMessageContext) CompletableFuture(java.util.concurrent.CompletableFuture) HttpChunkedInput(io.netty.handler.codec.http.HttpChunkedInput) DefaultHttpRequest(io.netty.handler.codec.http.DefaultHttpRequest) Bootstrap(io.netty.bootstrap.Bootstrap) List(java.util.List) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener) JerseyChunkedInput(org.glassfish.jersey.netty.connector.internal.JerseyChunkedInput) DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) DefaultHttpRequest(io.netty.handler.codec.http.DefaultHttpRequest) HttpRequest(io.netty.handler.codec.http.HttpRequest) JdkSslContext(io.netty.handler.ssl.JdkSslContext) DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) SocketChannel(io.netty.channel.socket.SocketChannel) Channel(io.netty.channel.Channel) IOException(java.io.IOException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) ProcessingException(javax.ws.rs.ProcessingException) ChannelPipeline(io.netty.channel.ChannelPipeline) HttpContentDecompressor(io.netty.handler.codec.http.HttpContentDecompressor) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) ChunkedWriteHandler(io.netty.handler.stream.ChunkedWriteHandler) CompletableFuture(java.util.concurrent.CompletableFuture) Future(java.util.concurrent.Future) HttpProxyHandler(io.netty.handler.proxy.HttpProxyHandler) Map(java.util.Map)

Example 2 with GenericFutureListener

use of io.netty.util.concurrent.GenericFutureListener in project riposte by Nike-Inc.

the class StreamingAsyncHttpClientTest method StreamingChannel_streamChunk_sets_up_task_in_event_loop_to_call_doStreamChunk_and_adds_listener_to_complete_promise.

@Test
public void StreamingChannel_streamChunk_sets_up_task_in_event_loop_to_call_doStreamChunk_and_adds_listener_to_complete_promise() throws Exception {
    // given
    ChannelFuture doStreamChunkFutureMock = mock(ChannelFuture.class);
    doReturn(doStreamChunkFutureMock).when(streamingChannelSpy).doStreamChunk(any(HttpContent.class));
    // when
    ChannelFuture result = streamingChannelSpy.streamChunk(contentChunkMock);
    // then
    assertThat(result).isSameAs(streamChunkChannelPromiseMock);
    // not yet completed
    verifyZeroInteractions(streamChunkChannelPromiseMock);
    ArgumentCaptor<Runnable> taskCaptor = ArgumentCaptor.forClass(Runnable.class);
    verify(eventLoopMock).execute(taskCaptor.capture());
    Runnable task = taskCaptor.getValue();
    // and given
    // not yet called
    verify(streamingChannelSpy, never()).doStreamChunk(any(HttpContent.class));
    // when
    task.run();
    // then
    verify(streamingChannelSpy).doStreamChunk(contentChunkMock);
    ArgumentCaptor<GenericFutureListener> listenerCaptor = ArgumentCaptor.forClass(GenericFutureListener.class);
    verify(doStreamChunkFutureMock).addListener(listenerCaptor.capture());
    GenericFutureListener listener = listenerCaptor.getValue();
    assertThat(listener).isNotNull();
    // and when
    listener.operationComplete(getFutureForCase(true, false, null));
    // then
    verify(streamChunkChannelPromiseMock).cancel(true);
    verifyNoMoreInteractions(streamChunkChannelPromiseMock);
    // and when
    listener.operationComplete(getFutureForCase(false, true, null));
    // then
    verify(streamChunkChannelPromiseMock).setSuccess();
    verifyNoMoreInteractions(streamChunkChannelPromiseMock);
    // and when
    Throwable normalFutureFailure = new RuntimeException("normal future failure");
    listener.operationComplete(getFutureForCase(false, false, normalFutureFailure));
    // then
    verify(streamChunkChannelPromiseMock).setFailure(normalFutureFailure);
    verifyNoMoreInteractions(streamChunkChannelPromiseMock);
    // and when
    reset(streamChunkChannelPromiseMock);
    listener.operationComplete(getFutureForCase(false, false, null));
    // then
    ArgumentCaptor<Throwable> throwableCaptor = ArgumentCaptor.forClass(Throwable.class);
    verify(streamChunkChannelPromiseMock).setFailure(throwableCaptor.capture());
    assertThat(throwableCaptor.getValue()).hasMessage("Received ChannelFuture that was in an impossible state");
    verifyNoMoreInteractions(streamChunkChannelPromiseMock);
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) Assertions.catchThrowable(org.assertj.core.api.Assertions.catchThrowable) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) HttpContent(io.netty.handler.codec.http.HttpContent) Test(org.junit.Test)

Example 3 with GenericFutureListener

use of io.netty.util.concurrent.GenericFutureListener in project riposte by Nike-Inc.

the class ChannelPipelineFinalizerHandlerTest method finalizeChannelPipeline_should_send_event_to_metricsListener_for_failure_response_and_flush_context.

@Test
public void finalizeChannelPipeline_should_send_event_to_metricsListener_for_failure_response_and_flush_context() throws Exception {
    // given
    ChannelFuture responseWriterChannelFuture = mock(ChannelFuture.class);
    state.setResponseWriterFinalChunkChannelFuture(responseWriterChannelFuture);
    HttpProcessingState stateSpy = spy(state);
    doReturn(stateSpy).when(stateAttributeMock).get();
    ChannelFuture responseWriteFutureResult = mock(ChannelFuture.class);
    doReturn(false).when(responseWriteFutureResult).isSuccess();
    Assertions.assertThat(stateSpy.isRequestMetricsRecordedOrScheduled()).isFalse();
    // when
    handler.finalizeChannelPipeline(ctxMock, null, stateSpy, null);
    // then
    ArgumentCaptor<GenericFutureListener> channelFutureListenerArgumentCaptor = ArgumentCaptor.forClass(GenericFutureListener.class);
    verify(responseWriterChannelFuture).addListener(channelFutureListenerArgumentCaptor.capture());
    GenericFutureListener futureListener = channelFutureListenerArgumentCaptor.getValue();
    assertThat(futureListener, notNullValue());
    futureListener.operationComplete(responseWriteFutureResult);
    verify(metricsListenerMock).onEvent(ServerMetricsEvent.RESPONSE_WRITE_FAILED, null);
    verify(ctxMock).flush();
    Assertions.assertThat(stateSpy.isRequestMetricsRecordedOrScheduled()).isTrue();
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) HttpProcessingState(com.nike.riposte.server.http.HttpProcessingState) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener) Test(org.junit.Test)

Example 4 with GenericFutureListener

use of io.netty.util.concurrent.GenericFutureListener in project riposte by Nike-Inc.

the class ChannelPipelineFinalizerHandlerTest method finalizeChannelPipeline_should_send_event_to_metricsListener_for_successful_response_and_flush_context.

@Test
public void finalizeChannelPipeline_should_send_event_to_metricsListener_for_successful_response_and_flush_context() throws Exception {
    // given
    ChannelFuture responseWriterChannelFuture = mock(ChannelFuture.class);
    state.setResponseWriterFinalChunkChannelFuture(responseWriterChannelFuture);
    HttpProcessingState stateSpy = spy(state);
    doReturn(stateSpy).when(stateAttributeMock).get();
    ChannelFuture responseWriteFutureResult = mock(ChannelFuture.class);
    doReturn(true).when(responseWriteFutureResult).isSuccess();
    Assertions.assertThat(stateSpy.isRequestMetricsRecordedOrScheduled()).isFalse();
    // when
    handler.finalizeChannelPipeline(ctxMock, null, stateSpy, null);
    // then
    ArgumentCaptor<GenericFutureListener> channelFutureListenerArgumentCaptor = ArgumentCaptor.forClass(GenericFutureListener.class);
    verify(responseWriterChannelFuture).addListener(channelFutureListenerArgumentCaptor.capture());
    GenericFutureListener futureListener = channelFutureListenerArgumentCaptor.getValue();
    assertThat(futureListener, notNullValue());
    futureListener.operationComplete(responseWriteFutureResult);
    verify(metricsListenerMock).onEvent(eq(ServerMetricsEvent.RESPONSE_SENT), any(HttpProcessingState.class));
    verify(ctxMock).flush();
    Assertions.assertThat(stateSpy.isRequestMetricsRecordedOrScheduled()).isTrue();
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) HttpProcessingState(com.nike.riposte.server.http.HttpProcessingState) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener) Test(org.junit.Test)

Example 5 with GenericFutureListener

use of io.netty.util.concurrent.GenericFutureListener in project riposte by Nike-Inc.

the class OpenChannelLimitHandlerTest method doChannelActive_marks_and_schedules_double_check_timeout_if_too_many_open_channels.

@DataProvider(value = { "0", "1" })
@Test
public void doChannelActive_marks_and_schedules_double_check_timeout_if_too_many_open_channels(int numOpenChannelsGreaterThanMax) throws Exception {
    // given
    int actualOpenChannels = maxOpenChannelsThreshold + numOpenChannelsGreaterThanMax;
    setActualOpenChannels(actualOpenChannels);
    // when
    PipelineContinuationBehavior result = handler.doChannelActive(ctxMock);
    // then
    assertThat(result).isEqualTo(CONTINUE);
    Pair<Runnable, GenericFutureListener> futureInfoPair = extractDoubleCheckRunnableAndCloseFutureListener();
    verify(tooManyOpenConnectionsAttributeMock).set(actualOpenChannels);
    verifyDoubleCheckFuture(futureInfoPair.getLeft());
    verifyCloseFutureListener(futureInfoPair.getRight());
    verify(channelGroupMock, never()).add(channelMock);
}
Also used : PipelineContinuationBehavior(com.nike.riposte.server.handler.base.PipelineContinuationBehavior) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Aggregations

GenericFutureListener (io.netty.util.concurrent.GenericFutureListener)22 ChannelFuture (io.netty.channel.ChannelFuture)9 Future (io.netty.util.concurrent.Future)7 Future (io.vertx.core.Future)5 Handler (io.vertx.core.Handler)5 ContextInternal (io.vertx.core.impl.ContextInternal)5 VertxInternal (io.vertx.core.impl.VertxInternal)5 InetSocketAddress (java.net.InetSocketAddress)5 Bootstrap (io.netty.bootstrap.Bootstrap)4 ByteBuf (io.netty.buffer.ByteBuf)4 Channel (io.netty.channel.Channel)4 ChannelOption (io.netty.channel.ChannelOption)4 AsyncResult (io.vertx.core.AsyncResult)4 PromiseInternal (io.vertx.core.impl.future.PromiseInternal)4 SocketAddress (io.vertx.core.net.SocketAddress)4 IOException (java.io.IOException)4 Map (java.util.Map)4 Test (org.junit.Test)4 ServerBootstrap (io.netty.bootstrap.ServerBootstrap)3 LoggingHandler (io.netty.handler.logging.LoggingHandler)3