Search in sources :

Example 1 with DefaultStreamedHttpResponse

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);
}
Also used : NettyHttpHeaders(io.micronaut.http.netty.NettyHttpHeaders) MutableHttpHeaders(io.micronaut.http.MutableHttpHeaders) DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) URI(java.net.URI) Subscriber(org.reactivestreams.Subscriber) JsonSubscriber(io.micronaut.http.netty.stream.JsonSubscriber) Subscription(org.reactivestreams.Subscription) MutableHttpRequest(io.micronaut.http.MutableHttpRequest) AbstractNettyHttpRequest(io.micronaut.http.netty.AbstractNettyHttpRequest) StreamedHttpRequest(io.micronaut.http.netty.stream.StreamedHttpRequest) StreamedHttpResponse(io.micronaut.http.netty.stream.StreamedHttpResponse) DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) EmptyByteBuf(io.netty.buffer.EmptyByteBuf) HttpStatus(io.micronaut.http.HttpStatus) Flux(reactor.core.publisher.Flux) StreamedHttpResponse(io.micronaut.http.netty.stream.StreamedHttpResponse) DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) HttpResponse(io.micronaut.http.HttpResponse) MutableHttpResponse(io.micronaut.http.MutableHttpResponse) Publisher(org.reactivestreams.Publisher) MutableHttpRequest(io.micronaut.http.MutableHttpRequest) NoHostException(io.micronaut.http.client.exceptions.NoHostException) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) ReadTimeoutException(io.micronaut.http.client.exceptions.ReadTimeoutException) ContentLengthExceededException(io.micronaut.http.client.exceptions.ContentLengthExceededException) MultipartException(io.micronaut.http.multipart.MultipartException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) TimeoutException(java.util.concurrent.TimeoutException) CodecException(io.micronaut.http.codec.CodecException) TooLongFrameException(io.netty.handler.codec.TooLongFrameException) WebSocketSessionException(io.micronaut.websocket.exceptions.WebSocketSessionException) HttpClientException(io.micronaut.http.client.exceptions.HttpClientException) MalformedURLException(java.net.MalformedURLException) IdleStateEvent(io.netty.handler.timeout.IdleStateEvent) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) io.netty.handler.codec.http(io.netty.handler.codec.http)

Example 2 with DefaultStreamedHttpResponse

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;
}
Also used : HttpResponseWrapper(io.micronaut.http.HttpResponseWrapper) DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) StreamedHttpResponse(io.micronaut.http.netty.stream.StreamedHttpResponse) DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent) FullHttpResponse(io.netty.handler.codec.http.FullHttpResponse) DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) ByteBuf(io.netty.buffer.ByteBuf) NonNull(io.micronaut.core.annotation.NonNull)

Example 3 with DefaultStreamedHttpResponse

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;
}
Also used : DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent) FullHttpResponse(io.netty.handler.codec.http.FullHttpResponse) DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) NonNull(io.micronaut.core.annotation.NonNull)

Example 4 with DefaultStreamedHttpResponse

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;
}
Also used : DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent) ByteBuf(io.netty.buffer.ByteBuf) NonNull(io.micronaut.core.annotation.NonNull)

Aggregations

DefaultStreamedHttpResponse (io.micronaut.http.netty.stream.DefaultStreamedHttpResponse)4 NonNull (io.micronaut.core.annotation.NonNull)3 DefaultLastHttpContent (io.netty.handler.codec.http.DefaultLastHttpContent)3 StreamedHttpResponse (io.micronaut.http.netty.stream.StreamedHttpResponse)2 ByteBuf (io.netty.buffer.ByteBuf)2 DefaultFullHttpResponse (io.netty.handler.codec.http.DefaultFullHttpResponse)2 FullHttpResponse (io.netty.handler.codec.http.FullHttpResponse)2 HttpResponse (io.micronaut.http.HttpResponse)1 HttpResponseWrapper (io.micronaut.http.HttpResponseWrapper)1 HttpStatus (io.micronaut.http.HttpStatus)1 MutableHttpHeaders (io.micronaut.http.MutableHttpHeaders)1 MutableHttpRequest (io.micronaut.http.MutableHttpRequest)1 MutableHttpResponse (io.micronaut.http.MutableHttpResponse)1 ContentLengthExceededException (io.micronaut.http.client.exceptions.ContentLengthExceededException)1 HttpClientException (io.micronaut.http.client.exceptions.HttpClientException)1 HttpClientResponseException (io.micronaut.http.client.exceptions.HttpClientResponseException)1 NoHostException (io.micronaut.http.client.exceptions.NoHostException)1 ReadTimeoutException (io.micronaut.http.client.exceptions.ReadTimeoutException)1 CodecException (io.micronaut.http.codec.CodecException)1 MultipartException (io.micronaut.http.multipart.MultipartException)1