use of io.micronaut.http.netty.stream.DefaultStreamedHttpResponse in project micronaut-core by micronaut-projects.
the class DefaultHttpClient method streamRequestThroughChannel.
private void streamRequestThroughChannel(io.micronaut.http.HttpRequest<?> parentRequest, AtomicReference<io.micronaut.http.HttpRequest> requestWrapper, FluxSink emitter, Channel channel, boolean failOnError) throws HttpPostRequestEncoder.ErrorDataEncoderException {
io.micronaut.http.HttpRequest<?> finalRequest = requestWrapper.get();
URI requestURI = finalRequest.getUri();
NettyRequestWriter requestWriter = prepareRequest(finalRequest, requestURI, emitter, false);
HttpRequest nettyRequest = requestWriter.getNettyRequest();
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(ChannelPipelineCustomizer.HANDLER_MICRONAUT_HTTP_RESPONSE_FULL, new SimpleChannelInboundHandlerInstrumented<FullHttpResponse>() {
final AtomicBoolean received = new AtomicBoolean(false);
@Override
public boolean acceptInboundMessage(Object msg) {
return msg instanceof FullHttpResponse;
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (received.compareAndSet(false, true)) {
emitter.error(cause);
}
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent && received.compareAndSet(false, true)) {
// closed to idle ste
emitter.error(ReadTimeoutException.TIMEOUT_EXCEPTION);
}
}
@Override
protected void channelReadInstrumented(ChannelHandlerContext ctx, FullHttpResponse msg) {
if (received.compareAndSet(false, true)) {
HttpResponseStatus status = msg.status();
int statusCode = status.code();
HttpStatus httpStatus;
try {
httpStatus = HttpStatus.valueOf(statusCode);
} catch (IllegalArgumentException e) {
emitter.error(e);
return;
}
Publisher<HttpContent> bodyPublisher;
if (msg.content() instanceof EmptyByteBuf) {
bodyPublisher = Publishers.empty();
} else {
bodyPublisher = Publishers.just(new DefaultLastHttpContent(msg.content()));
}
DefaultStreamedHttpResponse nettyResponse = new DefaultStreamedHttpResponse(msg.protocolVersion(), msg.status(), msg.headers(), bodyPublisher);
NettyStreamedHttpResponse response = new NettyStreamedHttpResponse(nettyResponse, httpStatus);
HttpHeaders headers = msg.headers();
if (log.isTraceEnabled()) {
log.trace("HTTP Client Streaming Response Received ({}) for Request: {} {}", msg.status(), nettyRequest.method().name(), nettyRequest.uri());
traceHeaders(headers);
}
boolean errorStatus = statusCode >= 400;
if (errorStatus && failOnError) {
emitter.error(new HttpClientResponseException(response.getStatus().getReason(), response));
} else {
emitter.next(response);
emitter.complete();
}
}
}
});
pipeline.addLast(ChannelPipelineCustomizer.HANDLER_MICRONAUT_HTTP_RESPONSE_STREAM, new SimpleChannelInboundHandlerInstrumented<StreamedHttpResponse>() {
final AtomicBoolean received = new AtomicBoolean(false);
@Override
public boolean acceptInboundMessage(Object msg) {
return msg instanceof StreamedHttpResponse;
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (received.compareAndSet(false, true)) {
emitter.error(cause);
}
}
@Override
protected void channelReadInstrumented(ChannelHandlerContext ctx, StreamedHttpResponse msg) {
if (received.compareAndSet(false, true)) {
HttpResponseStatus status = msg.status();
int statusCode = status.code();
HttpStatus httpStatus;
try {
httpStatus = HttpStatus.valueOf(statusCode);
} catch (IllegalArgumentException e) {
emitter.error(e);
return;
}
NettyStreamedHttpResponse response = new NettyStreamedHttpResponse(msg, httpStatus);
HttpHeaders headers = msg.headers();
if (log.isTraceEnabled()) {
log.trace("HTTP Client Streaming Response Received ({}) for Request: {} {}", msg.status(), nettyRequest.method().name(), nettyRequest.uri());
traceHeaders(headers);
}
if (statusCode > 300 && statusCode < 400 && configuration.isFollowRedirects() && headers.contains(HttpHeaderNames.LOCATION)) {
String location = headers.get(HttpHeaderNames.LOCATION);
Flux<io.micronaut.http.HttpResponse<Object>> redirectedExchange;
try {
MutableHttpRequest<Object> redirectRequest;
if (statusCode == 307) {
redirectRequest = io.micronaut.http.HttpRequest.create(finalRequest.getMethod(), location);
finalRequest.getBody().ifPresent(redirectRequest::body);
} else {
redirectRequest = io.micronaut.http.HttpRequest.GET(location);
}
setRedirectHeaders(nettyRequest, redirectRequest);
redirectedExchange = Flux.from(resolveRedirectURI(parentRequest, redirectRequest)).flatMap(uri -> buildStreamExchange(parentRequest, redirectRequest, uri, null));
// noinspection SubscriberImplementation
redirectedExchange.subscribe(new Subscriber<io.micronaut.http.HttpResponse<Object>>() {
Subscription sub;
@Override
public void onSubscribe(Subscription s) {
s.request(1);
this.sub = s;
}
@Override
public void onNext(io.micronaut.http.HttpResponse<Object> objectHttpResponse) {
emitter.next(objectHttpResponse);
}
@Override
public void onError(Throwable t) {
emitter.error(t);
}
@Override
public void onComplete() {
emitter.complete();
}
});
} catch (Exception e) {
emitter.error(e);
}
} else {
boolean errorStatus = statusCode >= 400;
if (errorStatus && failOnError) {
emitter.error(new HttpClientResponseException(response.getStatus().getReason(), response));
} else {
emitter.next(response);
emitter.complete();
}
}
}
}
});
if (log.isDebugEnabled()) {
debugRequest(requestURI, nettyRequest);
}
if (log.isTraceEnabled()) {
traceRequest(requestWrapper.get(), nettyRequest);
}
requestWriter.writeAndClose(channel, null, emitter);
}
use of io.micronaut.http.netty.stream.DefaultStreamedHttpResponse in project micronaut-core by micronaut-projects.
the class NettyHttpResponseBuilder method toStreamResponse.
/**
* Convert the given response to a full http response.
* @param response The response
* @return The full response.
*/
@NonNull
static StreamedHttpResponse toStreamResponse(@NonNull io.micronaut.http.HttpResponse<?> response) {
Objects.requireNonNull(response, "The response cannot be null");
while (response instanceof HttpResponseWrapper) {
response = ((HttpResponseWrapper<?>) response).getDelegate();
}
if (response instanceof NettyHttpResponseBuilder) {
NettyHttpResponseBuilder builder = (NettyHttpResponseBuilder) response;
if (builder.isStream()) {
return builder.toStreamHttpResponse();
} else {
FullHttpResponse fullHttpResponse = builder.toFullHttpResponse();
return new DefaultStreamedHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(response.code(), response.reason()), Publishers.just(new DefaultLastHttpContent(fullHttpResponse.content())));
}
}
// manual conversion
StreamedHttpResponse fullHttpResponse;
ByteBuf byteBuf = response.getBody(ByteBuf.class).orElse(null);
if (byteBuf != null) {
fullHttpResponse = new DefaultStreamedHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(response.code(), response.reason()), Publishers.just(new DefaultLastHttpContent(byteBuf)));
} else {
fullHttpResponse = new DefaultStreamedHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(response.code(), response.reason()), Publishers.empty());
}
response.getHeaders().forEach((s, strings) -> fullHttpResponse.headers().add(s, strings));
return fullHttpResponse;
}
use of io.micronaut.http.netty.stream.DefaultStreamedHttpResponse in project micronaut-core by micronaut-projects.
the class NettyHttpResponseBuilder method toStreamHttpResponse.
/**
* Converts this object to a streamed http response.
* @return The streamed response
*/
@NonNull
default StreamedHttpResponse toStreamHttpResponse() {
FullHttpResponse fullHttpResponse = toFullHttpResponse();
DefaultStreamedHttpResponse streamedHttpResponse = new DefaultStreamedHttpResponse(fullHttpResponse.protocolVersion(), fullHttpResponse.status(), true, Publishers.just(new DefaultLastHttpContent(fullHttpResponse.content())));
streamedHttpResponse.headers().setAll(fullHttpResponse.headers());
return streamedHttpResponse;
}
use of io.micronaut.http.netty.stream.DefaultStreamedHttpResponse in project micronaut-core by micronaut-projects.
the class NettyMutableHttpResponse method toStreamHttpResponse.
@NonNull
@Override
public StreamedHttpResponse toStreamHttpResponse() {
ByteBuf content;
if (body == null) {
content = Unpooled.EMPTY_BUFFER;
} else if (body instanceof ByteBuf) {
content = (ByteBuf) body;
} else {
throw new IllegalStateException("Body needs to be converted to ByteBuf from " + body.getClass());
}
DefaultStreamedHttpResponse streamedHttpResponse = new DefaultStreamedHttpResponse(HttpVersion.HTTP_1_1, httpResponseStatus, true, Publishers.just(new DefaultLastHttpContent(content)));
streamedHttpResponse.headers().setAll(nettyHeaders);
return streamedHttpResponse;
}
Aggregations