Search in sources :

Example 1 with RESULT

use of io.helidon.webclient.WebClientRequestBuilderImpl.RESULT in project helidon by oracle.

the class NettyClientInitializer method initChannel.

@Override
protected void initChannel(SocketChannel channel) {
    ChannelPipeline pipeline = channel.pipeline();
    URI address = configuration.requestURI();
    // read timeout (we also want to timeout waiting on a proxy)
    Duration readTimeout = configuration.readTimout();
    pipeline.addLast("readTimeout", new HelidonReadTimeoutHandler(readTimeout.toMillis(), TimeUnit.MILLISECONDS));
    // proxy configuration
    configuration.proxy().flatMap(proxy -> proxy.handler(address)).ifPresent(it -> {
        ProxyHandler proxyHandler = (ProxyHandler) it;
        proxyHandler.setConnectTimeoutMillis(configuration.connectTimeout().toMillis());
        pipeline.addLast(proxyHandler);
    });
    // TLS configuration
    if (address.toString().startsWith("https")) {
        configuration.sslContext().ifPresent(ctx -> {
            SslHandler sslHandler = ctx.newHandler(channel.alloc(), address.getHost(), address.getPort());
            // This is how to enable hostname verification in netty
            if (!configuration.tls().disableHostnameVerification()) {
                SSLEngine sslEngine = sslHandler.engine();
                SSLParameters sslParameters = sslEngine.getSSLParameters();
                sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
                sslEngine.setSSLParameters(sslParameters);
            }
            pipeline.addLast("ssl", sslHandler);
            sslHandler.handshakeFuture().addListener((FutureListener<Channel>) channelFuture -> {
                if (channelFuture.cause() != null) {
                    channel.attr(RESULT).get().completeExceptionally(channelFuture.cause());
                    channel.close();
                }
            });
        });
    }
    pipeline.addLast("logger", new LoggingHandler(ClientNettyLog.class, LogLevel.TRACE));
    pipeline.addLast("httpCodec", new HttpClientCodec());
    pipeline.addLast("httpDecompressor", new HttpContentDecompressor());
    pipeline.addLast("idleStateHandler", new IdleStateHandler(0, 0, 50));
    pipeline.addLast("idleConnectionHandler", new IdleConnectionHandler());
    pipeline.addLast("helidonHandler", new NettyClientHandler());
}
Also used : LoggingHandler(io.netty.handler.logging.LoggingHandler) ProxyHandler(io.netty.handler.proxy.ProxyHandler) RECEIVED(io.helidon.webclient.WebClientRequestBuilderImpl.RECEIVED) SSLParameters(javax.net.ssl.SSLParameters) RESULT(io.helidon.webclient.WebClientRequestBuilderImpl.RESULT) CompletableFuture(java.util.concurrent.CompletableFuture) SSLEngine(javax.net.ssl.SSLEngine) HttpClientCodec(io.netty.handler.codec.http.HttpClientCodec) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) Duration(java.time.Duration) URI(java.net.URI) SocketChannel(io.netty.channel.socket.SocketChannel) ChannelDuplexHandler(io.netty.channel.ChannelDuplexHandler) IdleStateEvent(io.netty.handler.timeout.IdleStateEvent) ChannelInitializer(io.netty.channel.ChannelInitializer) FutureListener(io.netty.util.concurrent.FutureListener) ChannelPipeline(io.netty.channel.ChannelPipeline) Logger(java.util.logging.Logger) CONNECTION_IDENT(io.helidon.webclient.WebClientRequestBuilderImpl.CONNECTION_IDENT) TimeUnit(java.util.concurrent.TimeUnit) Channel(io.netty.channel.Channel) IN_USE(io.helidon.webclient.WebClientRequestBuilderImpl.IN_USE) IdleStateHandler(io.netty.handler.timeout.IdleStateHandler) LogLevel(io.netty.handler.logging.LogLevel) SslHandler(io.netty.handler.ssl.SslHandler) HttpContentDecompressor(io.netty.handler.codec.http.HttpContentDecompressor) RESPONSE_RECEIVED(io.helidon.webclient.WebClientRequestBuilderImpl.RESPONSE_RECEIVED) LoggingHandler(io.netty.handler.logging.LoggingHandler) ProxyHandler(io.netty.handler.proxy.ProxyHandler) SSLEngine(javax.net.ssl.SSLEngine) SocketChannel(io.netty.channel.socket.SocketChannel) Channel(io.netty.channel.Channel) Duration(java.time.Duration) HttpClientCodec(io.netty.handler.codec.http.HttpClientCodec) URI(java.net.URI) ChannelPipeline(io.netty.channel.ChannelPipeline) SslHandler(io.netty.handler.ssl.SslHandler) HttpContentDecompressor(io.netty.handler.codec.http.HttpContentDecompressor) SSLParameters(javax.net.ssl.SSLParameters) IdleStateHandler(io.netty.handler.timeout.IdleStateHandler)

Example 2 with RESULT

use of io.helidon.webclient.WebClientRequestBuilderImpl.RESULT in project helidon by oracle.

the class NettyClientHandler method channelRead0.

@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws IOException {
    Channel channel = ctx.channel();
    if (msg instanceof HttpResponse) {
        channel.config().setAutoRead(false);
        HttpResponse response = (HttpResponse) msg;
        this.requestId = channel.attr(REQUEST_ID).get();
        channel.attr(RESPONSE_RECEIVED).set(true);
        WebClientRequestImpl clientRequest = channel.attr(REQUEST).get();
        RequestConfiguration requestConfiguration = clientRequest.configuration();
        LOGGER.finest(() -> "(client reqID: " + requestId + ") Initial http response message received");
        this.publisher = new HttpResponsePublisher(ctx);
        channel.attr(PUBLISHER).set(this.publisher);
        this.responseCloser = new ResponseCloser(ctx);
        WebClientResponseImpl.Builder responseBuilder = WebClientResponseImpl.builder();
        responseBuilder.contentPublisher(publisher).readerContext(requestConfiguration.readerContext()).status(helidonStatus(response.status())).httpVersion(Http.Version.create(response.protocolVersion().toString())).responseCloser(responseCloser).lastEndpointURI(requestConfiguration.requestURI());
        HttpHeaders nettyHeaders = response.headers();
        for (String name : nettyHeaders.names()) {
            List<String> values = nettyHeaders.getAll(name);
            responseBuilder.addHeader(name, values);
        }
        String connection = nettyHeaders.get(Http.Header.CONNECTION, HttpHeaderValues.CLOSE.toString());
        if (connection.equals(HttpHeaderValues.CLOSE.toString())) {
            ctx.channel().attr(WILL_CLOSE).set(true);
        }
        // we got a response, we can safely complete the future
        // all errors are now fed only to the publisher
        WebClientResponse clientResponse = responseBuilder.build();
        channel.attr(RESPONSE).set(clientResponse);
        for (HttpInterceptor interceptor : HTTP_INTERCEPTORS) {
            if (interceptor.shouldIntercept(response.status(), requestConfiguration)) {
                boolean continueAfter = !interceptor.continueAfterInterception();
                if (continueAfter) {
                    responseCloser.close().thenAccept(future -> LOGGER.finest(() -> "Response closed due to redirection"));
                }
                interceptor.handleInterception(response, clientRequest, channel.attr(RESULT).get());
                if (continueAfter) {
                    return;
                }
            }
        }
        requestConfiguration.cookieManager().put(requestConfiguration.requestURI(), clientResponse.headers().toMap());
        WebClientServiceResponse clientServiceResponse = new WebClientServiceResponseImpl(requestConfiguration.context().get(), clientResponse.headers(), clientResponse.status());
        channel.attr(SERVICE_RESPONSE).set(clientServiceResponse);
        List<WebClientService> services = requestConfiguration.services();
        CompletionStage<WebClientServiceResponse> csr = CompletableFuture.completedFuture(clientServiceResponse);
        for (WebClientService service : services) {
            csr = csr.thenCompose(clientSerResponse -> service.response(clientRequest, clientSerResponse));
        }
        CompletableFuture<WebClientServiceResponse> responseReceived = channel.attr(RECEIVED).get();
        CompletableFuture<WebClientResponse> responseFuture = channel.attr(RESULT).get();
        csr.whenComplete((clientSerResponse, throwable) -> {
            if (throwable != null) {
                responseReceived.completeExceptionally(throwable);
                responseFuture.completeExceptionally(throwable);
                responseCloser.close();
            } else {
                responseReceived.complete(clientServiceResponse);
                responseReceived.thenRun(() -> {
                    if (shouldResponseAutomaticallyClose(clientResponse)) {
                        responseCloser.close().thenAccept(aVoid -> {
                            LOGGER.finest(() -> "Response automatically closed. No entity expected");
                        });
                    }
                    responseFuture.complete(clientResponse);
                });
            }
        });
    }
    if (responseCloser.isClosed()) {
        if (!channel.attr(WILL_CLOSE).get() && channel.hasAttr(RETURN)) {
            if (msg instanceof LastHttpContent) {
                LOGGER.finest(() -> "(client reqID: " + requestId + ") Draining finished");
                if (channel.isActive()) {
                    channel.attr(RETURN).get().set(true);
                }
            } else {
                LOGGER.finest(() -> "(client reqID: " + requestId + ") Draining not finished, requesting new chunk");
            }
            channel.read();
        }
        return;
    }
    // never "else-if" - msg may be an instance of more than one type, we must process all of them
    if (msg instanceof HttpContent) {
        HttpContent content = (HttpContent) msg;
        publisher.emit(content.content());
    }
    if (msg instanceof LastHttpContent) {
        LOGGER.finest(() -> "(client reqID: " + requestId + ") Last http content received");
        if (channel.hasAttr(RETURN)) {
            channel.attr(RETURN).get().set(true);
            responseCloser.close();
            channel.read();
        } else {
            responseCloser.close();
        }
    }
}
Also used : BufferedEmittingPublisher(io.helidon.common.reactive.BufferedEmittingPublisher) AttributeKey(io.netty.util.AttributeKey) HttpHeaders(io.netty.handler.codec.http.HttpHeaders) COMPLETED(io.helidon.webclient.WebClientRequestBuilderImpl.COMPLETED) RECEIVED(io.helidon.webclient.WebClientRequestBuilderImpl.RECEIVED) DataChunk(io.helidon.common.http.DataChunk) RESULT(io.helidon.webclient.WebClientRequestBuilderImpl.RESULT) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) ReentrantReadWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock) HttpObject(io.netty.handler.codec.http.HttpObject) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) RESPONSE(io.helidon.webclient.WebClientRequestBuilderImpl.RESPONSE) ByteBuf(io.netty.buffer.ByteBuf) Single(io.helidon.common.reactive.Single) Http(io.helidon.common.http.Http) REQUEST(io.helidon.webclient.WebClientRequestBuilderImpl.REQUEST) HttpContent(io.netty.handler.codec.http.HttpContent) WILL_CLOSE(io.helidon.webclient.WebClientRequestBuilderImpl.WILL_CLOSE) WebClientService(io.helidon.webclient.spi.WebClientService) HttpHeaderValues(io.netty.handler.codec.http.HttpHeaderValues) REQUEST_ID(io.helidon.webclient.WebClientRequestBuilderImpl.REQUEST_ID) IOException(java.io.IOException) HttpResponseStatus(io.netty.handler.codec.http.HttpResponseStatus) Logger(java.util.logging.Logger) Channel(io.netty.channel.Channel) IN_USE(io.helidon.webclient.WebClientRequestBuilderImpl.IN_USE) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) SimpleChannelInboundHandler(io.netty.channel.SimpleChannelInboundHandler) HttpResponse(io.netty.handler.codec.http.HttpResponse) RETURN(io.helidon.webclient.WebClientRequestBuilderImpl.RETURN) RESPONSE_RECEIVED(io.helidon.webclient.WebClientRequestBuilderImpl.RESPONSE_RECEIVED) HttpHeaders(io.netty.handler.codec.http.HttpHeaders) Channel(io.netty.channel.Channel) HttpResponse(io.netty.handler.codec.http.HttpResponse) WebClientService(io.helidon.webclient.spi.WebClientService) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) HttpContent(io.netty.handler.codec.http.HttpContent)

Aggregations

IN_USE (io.helidon.webclient.WebClientRequestBuilderImpl.IN_USE)2 RECEIVED (io.helidon.webclient.WebClientRequestBuilderImpl.RECEIVED)2 RESPONSE_RECEIVED (io.helidon.webclient.WebClientRequestBuilderImpl.RESPONSE_RECEIVED)2 RESULT (io.helidon.webclient.WebClientRequestBuilderImpl.RESULT)2 Channel (io.netty.channel.Channel)2 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 Logger (java.util.logging.Logger)2 DataChunk (io.helidon.common.http.DataChunk)1 Http (io.helidon.common.http.Http)1 BufferedEmittingPublisher (io.helidon.common.reactive.BufferedEmittingPublisher)1 Single (io.helidon.common.reactive.Single)1 COMPLETED (io.helidon.webclient.WebClientRequestBuilderImpl.COMPLETED)1 CONNECTION_IDENT (io.helidon.webclient.WebClientRequestBuilderImpl.CONNECTION_IDENT)1 REQUEST (io.helidon.webclient.WebClientRequestBuilderImpl.REQUEST)1 REQUEST_ID (io.helidon.webclient.WebClientRequestBuilderImpl.REQUEST_ID)1 RESPONSE (io.helidon.webclient.WebClientRequestBuilderImpl.RESPONSE)1 RETURN (io.helidon.webclient.WebClientRequestBuilderImpl.RETURN)1 WILL_CLOSE (io.helidon.webclient.WebClientRequestBuilderImpl.WILL_CLOSE)1 WebClientService (io.helidon.webclient.spi.WebClientService)1