use of io.helidon.webclient.WebClientRequestBuilderImpl.RESPONSE 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