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());
}
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();
}
}
}
Aggregations