Search in sources :

Example 1 with MediaTypeCodecRegistry

use of io.micronaut.http.codec.MediaTypeCodecRegistry in project micronaut-core by micronaut-projects.

the class DefaultHttpClient method buildNettyRequest.

/**
 * @param request                The request
 * @param requestURI             The URI of the request
 * @param requestContentType     The request content type
 * @param permitsBody            Whether permits body
 * @param bodyType               The body type
 * @param onError                Called when the body publisher encounters an error
 * @param closeChannelAfterWrite Whether to close the channel. For stream requests we don't close the channel until disposed of.
 * @return A {@link NettyRequestWriter}
 * @throws HttpPostRequestEncoder.ErrorDataEncoderException if there is an encoder exception
 */
protected NettyRequestWriter buildNettyRequest(MutableHttpRequest request, URI requestURI, MediaType requestContentType, boolean permitsBody, @Nullable Argument<?> bodyType, Consumer<? super Throwable> onError, boolean closeChannelAfterWrite) throws HttpPostRequestEncoder.ErrorDataEncoderException {
    io.netty.handler.codec.http.HttpRequest nettyRequest;
    HttpPostRequestEncoder postRequestEncoder = null;
    if (permitsBody) {
        Optional body = request.getBody();
        boolean hasBody = body.isPresent();
        if (requestContentType.equals(MediaType.APPLICATION_FORM_URLENCODED_TYPE) && hasBody) {
            Object bodyValue = body.get();
            if (bodyValue instanceof CharSequence) {
                ByteBuf byteBuf = charSequenceToByteBuf((CharSequence) bodyValue, requestContentType);
                request.body(byteBuf);
                nettyRequest = NettyHttpRequestBuilder.toHttpRequest(request);
            } else {
                postRequestEncoder = buildFormDataRequest(request, bodyValue);
                nettyRequest = postRequestEncoder.finalizeRequest();
            }
        } else if (requestContentType.equals(MediaType.MULTIPART_FORM_DATA_TYPE) && hasBody) {
            Object bodyValue = body.get();
            postRequestEncoder = buildMultipartRequest(request, bodyValue);
            nettyRequest = postRequestEncoder.finalizeRequest();
        } else {
            ByteBuf bodyContent = null;
            if (hasBody) {
                Object bodyValue = body.get();
                if (Publishers.isConvertibleToPublisher(bodyValue)) {
                    boolean isSingle = Publishers.isSingle(bodyValue.getClass());
                    Publisher<?> publisher = ConversionService.SHARED.convert(bodyValue, Publisher.class).orElseThrow(() -> new IllegalArgumentException("Unconvertible reactive type: " + bodyValue));
                    Flux<HttpContent> requestBodyPublisher = Flux.from(publisher).map(o -> {
                        if (o instanceof CharSequence) {
                            ByteBuf textChunk = Unpooled.copiedBuffer(((CharSequence) o), requestContentType.getCharset().orElse(StandardCharsets.UTF_8));
                            if (log.isTraceEnabled()) {
                                traceChunk(textChunk);
                            }
                            return new DefaultHttpContent(textChunk);
                        } else if (o instanceof ByteBuf) {
                            ByteBuf byteBuf = (ByteBuf) o;
                            if (log.isTraceEnabled()) {
                                log.trace("Sending Bytes Chunk. Length: {}", byteBuf.readableBytes());
                            }
                            return new DefaultHttpContent(byteBuf);
                        } else if (o instanceof byte[]) {
                            byte[] bodyBytes = (byte[]) o;
                            if (log.isTraceEnabled()) {
                                log.trace("Sending Bytes Chunk. Length: {}", bodyBytes.length);
                            }
                            return new DefaultHttpContent(Unpooled.wrappedBuffer(bodyBytes));
                        } else if (o instanceof ByteBuffer) {
                            ByteBuffer<?> byteBuffer = (ByteBuffer<?>) o;
                            Object nativeBuffer = byteBuffer.asNativeBuffer();
                            if (log.isTraceEnabled()) {
                                log.trace("Sending Bytes Chunk. Length: {}", byteBuffer.readableBytes());
                            }
                            if (nativeBuffer instanceof ByteBuf) {
                                return new DefaultHttpContent((ByteBuf) nativeBuffer);
                            } else {
                                return new DefaultHttpContent(Unpooled.wrappedBuffer(byteBuffer.toByteArray()));
                            }
                        } else if (mediaTypeCodecRegistry != null) {
                            Optional<MediaTypeCodec> registeredCodec = mediaTypeCodecRegistry.findCodec(requestContentType);
                            ByteBuf encoded = registeredCodec.map(codec -> {
                                if (bodyType != null && bodyType.isInstance(o)) {
                                    return codec.encode((Argument<Object>) bodyType, o, byteBufferFactory).asNativeBuffer();
                                } else {
                                    return codec.encode(o, byteBufferFactory).asNativeBuffer();
                                }
                            }).orElse(null);
                            if (encoded != null) {
                                if (log.isTraceEnabled()) {
                                    traceChunk(encoded);
                                }
                                return new DefaultHttpContent(encoded);
                            }
                        }
                        throw new CodecException("Cannot encode value [" + o + "]. No possible encoders found");
                    });
                    if (!isSingle && MediaType.APPLICATION_JSON_TYPE.equals(requestContentType)) {
                        requestBodyPublisher = JsonSubscriber.lift(requestBodyPublisher);
                    }
                    requestBodyPublisher = requestBodyPublisher.doOnError(onError);
                    request.body(requestBodyPublisher);
                    nettyRequest = NettyHttpRequestBuilder.toHttpRequest(request);
                    try {
                        nettyRequest.setUri(requestURI.toURL().getFile());
                    } catch (MalformedURLException e) {
                    // should never happen
                    }
                    return new NettyRequestWriter(requestURI.getScheme(), nettyRequest, null, closeChannelAfterWrite);
                } else if (bodyValue instanceof CharSequence) {
                    bodyContent = charSequenceToByteBuf((CharSequence) bodyValue, requestContentType);
                } else if (mediaTypeCodecRegistry != null) {
                    Optional<MediaTypeCodec> registeredCodec = mediaTypeCodecRegistry.findCodec(requestContentType);
                    bodyContent = registeredCodec.map(codec -> {
                        if (bodyType != null && bodyType.isInstance(bodyValue)) {
                            return codec.encode((Argument<Object>) bodyType, bodyValue, byteBufferFactory).asNativeBuffer();
                        } else {
                            return codec.encode(bodyValue, byteBufferFactory).asNativeBuffer();
                        }
                    }).orElse(null);
                }
                if (bodyContent == null) {
                    bodyContent = ConversionService.SHARED.convert(bodyValue, ByteBuf.class).orElseThrow(() -> new HttpClientException("Body [" + bodyValue + "] cannot be encoded to content type [" + requestContentType + "]. No possible codecs or converters found."));
                }
            }
            request.body(bodyContent);
            try {
                nettyRequest = NettyHttpRequestBuilder.toHttpRequest(request);
            } finally {
                // reset body after encoding request in case of retry
                request.body(body.orElse(null));
            }
        }
    } else {
        nettyRequest = NettyHttpRequestBuilder.toHttpRequest(request);
    }
    try {
        nettyRequest.setUri(requestURI.toURL().getFile());
    } catch (MalformedURLException e) {
    // should never happen
    }
    return new NettyRequestWriter(requestURI.getScheme(), nettyRequest, postRequestEncoder, closeChannelAfterWrite);
}
Also used : AttributeKey(io.netty.util.AttributeKey) OrderUtil(io.micronaut.core.order.OrderUtil) Publishers(io.micronaut.core.async.publisher.Publishers) NoHostException(io.micronaut.http.client.exceptions.NoHostException) Processor(org.reactivestreams.Processor) JacksonDatabindMapper(io.micronaut.jackson.databind.JacksonDatabindMapper) ProxyHttpClient(io.micronaut.http.client.ProxyHttpClient) HttpProxyHandler(io.netty.handler.proxy.HttpProxyHandler) SseClient(io.micronaut.http.client.sse.SseClient) ChunkedWriteHandler(io.netty.handler.stream.ChunkedWriteHandler) HANDLER_IDLE_STATE(io.micronaut.http.netty.channel.ChannelPipelineCustomizer.HANDLER_IDLE_STATE) Internal(io.micronaut.core.annotation.Internal) NettyClientSslBuilder(io.micronaut.http.client.netty.ssl.NettyClientSslBuilder) Proxy(java.net.Proxy) InstantiationUtils(io.micronaut.core.reflect.InstantiationUtils) HttpStatus(io.micronaut.http.HttpStatus) Duration(java.time.Duration) CharsetUtil(io.netty.util.CharsetUtil) HANDLER_HTTP2_SETTINGS(io.micronaut.http.netty.channel.ChannelPipelineCustomizer.HANDLER_HTTP2_SETTINGS) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) ArgumentUtils(io.micronaut.core.util.ArgumentUtils) WebSocketClientHandshakerFactory(io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory) MapperMediaTypeCodec(io.micronaut.json.codec.MapperMediaTypeCodec) LoadBalancer(io.micronaut.http.client.LoadBalancer) SocketChannel(io.netty.channel.socket.SocketChannel) HttpClientErrorDecoder(io.micronaut.http.client.exceptions.HttpClientErrorDecoder) ResourceResolver(io.micronaut.core.io.ResourceResolver) ByteBufferFactory(io.micronaut.core.io.buffer.ByteBufferFactory) ReadTimeoutException(io.micronaut.http.client.exceptions.ReadTimeoutException) IdleStateEvent(io.netty.handler.timeout.IdleStateEvent) ChannelHealthChecker(io.netty.channel.pool.ChannelHealthChecker) StreamingInboundHttp2ToHttpAdapter(io.micronaut.http.netty.stream.StreamingInboundHttp2ToHttpAdapter) StandardCharsets(java.nio.charset.StandardCharsets) HttpFilterResolver(io.micronaut.http.filter.HttpFilterResolver) ClientFilterResolutionContext(io.micronaut.http.client.filter.ClientFilterResolutionContext) LineBasedFrameDecoder(io.netty.handler.codec.LineBasedFrameDecoder) AbstractChannelPoolHandler(io.netty.channel.pool.AbstractChannelPoolHandler) SslHandler(io.netty.handler.ssl.SslHandler) ReferenceCountUtil(io.netty.util.ReferenceCountUtil) MutableHttpRequest(io.micronaut.http.MutableHttpRequest) NettyWebSocketClientHandler(io.micronaut.http.client.netty.websocket.NettyWebSocketClientHandler) ChannelPoolMap(io.netty.channel.pool.ChannelPoolMap) MultipartDataFactory(io.micronaut.http.client.multipart.MultipartDataFactory) NettyByteBufferFactory(io.micronaut.buffer.netty.NettyByteBufferFactory) java.util(java.util) Disposable(reactor.core.Disposable) WebSocketBean(io.micronaut.websocket.context.WebSocketBean) OnMessage(io.micronaut.websocket.annotation.OnMessage) ContentLengthExceededException(io.micronaut.http.client.exceptions.ContentLengthExceededException) Supplier(java.util.function.Supplier) StreamedHttpResponse(io.micronaut.http.netty.stream.StreamedHttpResponse) NettyThreadFactory(io.micronaut.http.netty.channel.NettyThreadFactory) NettyHttpRequestBuilder(io.micronaut.http.netty.NettyHttpRequestBuilder) DefaultHttpClientConfiguration(io.micronaut.http.client.DefaultHttpClientConfiguration) NettyHttpHeaders(io.micronaut.http.netty.NettyHttpHeaders) Nullable(io.micronaut.core.annotation.Nullable) ByteBuffer(io.micronaut.core.io.buffer.ByteBuffer) JsonStreamMediaTypeCodec(io.micronaut.json.codec.JsonStreamMediaTypeCodec) Argument(io.micronaut.core.type.Argument) MultipartException(io.micronaut.http.multipart.MultipartException) ConversionService(io.micronaut.core.convert.ConversionService) ServerRequestContext(io.micronaut.http.context.ServerRequestContext) NOOP(io.micronaut.scheduling.instrument.InvocationInstrumenter.NOOP) MediaTypeCodecRegistry(io.micronaut.http.codec.MediaTypeCodecRegistry) Attribute(io.netty.util.Attribute) JsonNode(io.micronaut.json.tree.JsonNode) SslContext(io.netty.handler.ssl.SslContext) FileUpload(io.netty.handler.codec.http.multipart.FileUpload) Publisher(org.reactivestreams.Publisher) HttpClientConfiguration(io.micronaut.http.client.HttpClientConfiguration) Mono(reactor.core.publisher.Mono) IOException(java.io.IOException) NettyHttpResponseBuilder(io.micronaut.http.netty.NettyHttpResponseBuilder) File(java.io.File) AbstractNettyHttpRequest(io.micronaut.http.netty.AbstractNettyHttpRequest) SimpleChannelPool(io.netty.channel.pool.SimpleChannelPool) Bootstrap(io.netty.bootstrap.Bootstrap) Flux(reactor.core.publisher.Flux) WebSocketClientCompressionHandler(io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler) DEFAULT_SHUTDOWN_TIMEOUT_MILLISECONDS(io.micronaut.http.client.HttpClientConfiguration.DEFAULT_SHUTDOWN_TIMEOUT_MILLISECONDS) ChannelPipelineCustomizer(io.micronaut.http.netty.channel.ChannelPipelineCustomizer) ChannelPool(io.netty.channel.pool.ChannelPool) Instrumentation(io.micronaut.scheduling.instrument.Instrumentation) WebSocketClient(io.micronaut.websocket.WebSocketClient) Future(io.netty.util.concurrent.Future) DefaultThreadFactory(io.netty.util.concurrent.DefaultThreadFactory) ChannelPipelineListener(io.micronaut.http.netty.channel.ChannelPipelineListener) DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) SocketAddress(java.net.SocketAddress) HttpStreamsClientHandler(io.micronaut.http.netty.stream.HttpStreamsClientHandler) UriTemplate(io.micronaut.http.uri.UriTemplate) io.netty.handler.codec.http2(io.netty.handler.codec.http2) ByteBufAllocator(io.netty.buffer.ByteBufAllocator) URISyntaxException(java.net.URISyntaxException) DEFAULT_SHUTDOWN_QUIET_PERIOD_MILLISECONDS(io.micronaut.http.client.HttpClientConfiguration.DEFAULT_SHUTDOWN_QUIET_PERIOD_MILLISECONDS) ArrayUtils(io.micronaut.core.util.ArrayUtils) LoggerFactory(org.slf4j.LoggerFactory) TimeoutException(java.util.concurrent.TimeoutException) InvocationInstrumenter(io.micronaut.scheduling.instrument.InvocationInstrumenter) InvocationInstrumenterFactory(io.micronaut.scheduling.instrument.InvocationInstrumenterFactory) ClientFilterChain(io.micronaut.http.filter.ClientFilterChain) DefaultHttp2Content(io.micronaut.http.netty.stream.DefaultHttp2Content) Event(io.micronaut.http.sse.Event) Unpooled(io.netty.buffer.Unpooled) FixedChannelPool(io.netty.channel.pool.FixedChannelPool) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) MediaType(io.micronaut.http.MediaType) ReferenceCounted(io.micronaut.core.io.buffer.ReferenceCounted) JsonMapper(io.micronaut.json.JsonMapper) ApplicationProtocolNegotiationHandler(io.netty.handler.ssl.ApplicationProtocolNegotiationHandler) HttpResponse(io.micronaut.http.HttpResponse) ApplicationConfiguration(io.micronaut.runtime.ApplicationConfiguration) URI(java.net.URI) HttpClient(io.micronaut.http.client.HttpClient) HttpDataFactory(io.netty.handler.codec.http.multipart.HttpDataFactory) ThreadFactory(java.util.concurrent.ThreadFactory) RequestBinderRegistry(io.micronaut.http.bind.RequestBinderRegistry) MultipartBody(io.micronaut.http.client.multipart.MultipartBody) JsonMediaTypeCodec(io.micronaut.json.codec.JsonMediaTypeCodec) CodecException(io.micronaut.http.codec.CodecException) ReadTimeoutHandler(io.netty.handler.timeout.ReadTimeoutHandler) MutableHttpResponse(io.micronaut.http.MutableHttpResponse) MutableHttpHeaders(io.micronaut.http.MutableHttpHeaders) TooLongFrameException(io.netty.handler.codec.TooLongFrameException) InterfaceHttpData(io.netty.handler.codec.http.multipart.InterfaceHttpData) InetSocketAddress(java.net.InetSocketAddress) Collectors(java.util.stream.Collectors) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) StringUtils(io.micronaut.core.util.StringUtils) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) HttpClientFilter(io.micronaut.http.filter.HttpClientFilter) StreamedHttpRequest(io.micronaut.http.netty.stream.StreamedHttpRequest) io.netty.handler.codec.http(io.netty.handler.codec.http) StreamingHttpClient(io.micronaut.http.client.StreamingHttpClient) WebSocketSessionException(io.micronaut.websocket.exceptions.WebSocketSessionException) Type(java.net.Proxy.Type) Socks5ProxyHandler(io.netty.handler.proxy.Socks5ProxyHandler) ClientWebSocket(io.micronaut.websocket.annotation.ClientWebSocket) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) ClientServerContextFilter(io.micronaut.http.client.filters.ClientServerContextFilter) LoggingHandler(io.netty.handler.logging.LoggingHandler) UriBuilder(io.micronaut.http.uri.UriBuilder) HttpPostRequestEncoder(io.netty.handler.codec.http.multipart.HttpPostRequestEncoder) FluxSink(reactor.core.publisher.FluxSink) DefaultHttpDataFactory(io.netty.handler.codec.http.multipart.DefaultHttpDataFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HttpClientFilterResolver(io.micronaut.http.filter.HttpClientFilterResolver) Scheduler(reactor.core.scheduler.Scheduler) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) WebSocketBeanRegistry(io.micronaut.websocket.context.WebSocketBeanRegistry) BeanMap(io.micronaut.core.beans.BeanMap) NoopAddressResolverGroup(io.netty.resolver.NoopAddressResolverGroup) WebSocketVersion(io.netty.handler.codec.http.websocketx.WebSocketVersion) BlockingHttpClient(io.micronaut.http.client.BlockingHttpClient) ByteBuf(io.netty.buffer.ByteBuf) Charset(java.nio.charset.Charset) HttpClientException(io.micronaut.http.client.exceptions.HttpClientException) io.netty.channel(io.netty.channel) Schedulers(reactor.core.scheduler.Schedulers) HttpResponseWrapper(io.micronaut.http.HttpResponseWrapper) Subscriber(org.reactivestreams.Subscriber) MediaTypeCodec(io.micronaut.http.codec.MediaTypeCodec) Logger(org.slf4j.Logger) DefaultRequestBinderRegistry(io.micronaut.http.bind.DefaultRequestBinderRegistry) MalformedURLException(java.net.MalformedURLException) AnnotationMetadataResolver(io.micronaut.core.annotation.AnnotationMetadataResolver) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener) ApplicationProtocolNames(io.netty.handler.ssl.ApplicationProtocolNames) DefaultHttpClientFilterResolver(io.micronaut.http.client.filter.DefaultHttpClientFilterResolver) Http2Content(io.micronaut.http.netty.stream.Http2Content) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) NonNull(io.micronaut.core.annotation.NonNull) IdleStateHandler(io.netty.handler.timeout.IdleStateHandler) ByteBufUtil(io.netty.buffer.ByteBufUtil) EmptyByteBuf(io.netty.buffer.EmptyByteBuf) CollectionUtils(io.micronaut.core.util.CollectionUtils) Subscription(org.reactivestreams.Subscription) Closeable(java.io.Closeable) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) AbstractChannelPoolMap(io.netty.channel.pool.AbstractChannelPoolMap) JsonSubscriber(io.micronaut.http.netty.stream.JsonSubscriber) InputStream(java.io.InputStream) MalformedURLException(java.net.MalformedURLException) Argument(io.micronaut.core.type.Argument) HttpPostRequestEncoder(io.netty.handler.codec.http.multipart.HttpPostRequestEncoder) Flux(reactor.core.publisher.Flux) Publisher(org.reactivestreams.Publisher) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) ByteBuf(io.netty.buffer.ByteBuf) EmptyByteBuf(io.netty.buffer.EmptyByteBuf) ByteBuffer(io.micronaut.core.io.buffer.ByteBuffer) HttpClientException(io.micronaut.http.client.exceptions.HttpClientException) io.netty.handler.codec.http(io.netty.handler.codec.http) CodecException(io.micronaut.http.codec.CodecException)

Example 2 with MediaTypeCodecRegistry

use of io.micronaut.http.codec.MediaTypeCodecRegistry in project micronaut-core by micronaut-projects.

the class StreamFunctionExecutor method encode.

/**
 * Encode and write to output stream.
 *
 * @param environment environment
 * @param registry local function registry
 * @param returnType return type as Class
 * @param result result object
 * @param output outputstream
 * @throws IOException input/output exception
 */
static void encode(Environment environment, LocalFunctionRegistry registry, Class returnType, Object result, OutputStream output) throws IOException {
    if (ClassUtils.isJavaLangType(returnType)) {
        if (result instanceof Byte) {
            output.write((Byte) result);
        } else if (result instanceof Boolean) {
            output.write(((Boolean) result) ? 1 : 0);
        } else if (result instanceof byte[]) {
            output.write((byte[]) result);
        } else {
            byte[] bytes = environment.convert(result.toString(), byte[].class).orElseThrow(() -> new InvocationException("Unable to convert result [" + result + "] for output stream"));
            output.write(bytes);
        }
    } else {
        if (result instanceof Writable) {
            Writable writable = (Writable) result;
            writable.writeTo(output, environment.getProperty(LocalFunctionRegistry.FUNCTION_CHARSET, Charset.class, StandardCharsets.UTF_8));
        } else {
            Optional<MediaTypeCodec> codec = registry instanceof MediaTypeCodecRegistry ? ((MediaTypeCodecRegistry) registry).findCodec(MediaType.APPLICATION_JSON_TYPE) : Optional.empty();
            if (codec.isPresent()) {
                codec.get().encode(result, output);
            } else {
                byte[] bytes = environment.convert(result, byte[].class).orElseThrow(() -> new InvocationException("Unable to convert result [" + result + "] for output stream"));
                output.write(bytes);
            }
        }
    }
}
Also used : InvocationException(io.micronaut.core.reflect.exception.InvocationException) Writable(io.micronaut.core.io.Writable) Charset(java.nio.charset.Charset) MediaTypeCodecRegistry(io.micronaut.http.codec.MediaTypeCodecRegistry) MediaTypeCodec(io.micronaut.http.codec.MediaTypeCodec)

Example 3 with MediaTypeCodecRegistry

use of io.micronaut.http.codec.MediaTypeCodecRegistry in project micronaut-core by micronaut-projects.

the class DefaultNettyHttpClientRegistry method getClient.

private DefaultHttpClient getClient(ClientKey key, BeanContext beanContext, AnnotationMetadata annotationMetadata) {
    return clients.computeIfAbsent(key, clientKey -> {
        DefaultHttpClient clientBean = null;
        final String clientId = clientKey.clientId;
        final Class<?> configurationClass = clientKey.configurationClass;
        if (clientId != null) {
            clientBean = (DefaultHttpClient) this.beanContext.findBean(HttpClient.class, Qualifiers.byName(clientId)).orElse(null);
        }
        if (configurationClass != null && !HttpClientConfiguration.class.isAssignableFrom(configurationClass)) {
            throw new IllegalStateException("Referenced HTTP client configuration class must be an instance of HttpClientConfiguration for injection point: " + configurationClass);
        }
        final List<String> filterAnnotations = clientKey.filterAnnotations;
        final String path = clientKey.path;
        if (clientBean != null && path == null && configurationClass == null && filterAnnotations.isEmpty()) {
            return clientBean;
        }
        LoadBalancer loadBalancer = null;
        List<String> clientIdentifiers = null;
        final HttpClientConfiguration configuration;
        if (configurationClass != null) {
            configuration = (HttpClientConfiguration) this.beanContext.getBean(configurationClass);
        } else if (clientId != null) {
            configuration = this.beanContext.findBean(HttpClientConfiguration.class, Qualifiers.byName(clientId)).orElse(defaultHttpClientConfiguration);
        } else {
            configuration = defaultHttpClientConfiguration;
        }
        if (clientId != null) {
            loadBalancer = loadBalancerResolver.resolve(clientId).orElseThrow(() -> new HttpClientException("Invalid service reference [" + clientId + "] specified to @Client"));
            clientIdentifiers = Collections.singletonList(clientId);
        }
        String contextPath = null;
        if (StringUtils.isNotEmpty(path)) {
            contextPath = path;
        } else if (StringUtils.isNotEmpty(clientId) && clientId.startsWith("/")) {
            contextPath = clientId;
        } else {
            if (loadBalancer != null) {
                contextPath = loadBalancer.getContextPath().orElse(null);
            }
        }
        final DefaultHttpClient client = buildClient(loadBalancer, clientKey.httpVersion, configuration, clientIdentifiers, contextPath, beanContext, annotationMetadata);
        final JsonFeatures jsonFeatures = clientKey.jsonFeatures;
        if (jsonFeatures != null) {
            List<MediaTypeCodec> codecs = new ArrayList<>(2);
            MediaTypeCodecRegistry codecRegistry = client.getMediaTypeCodecRegistry();
            for (MediaTypeCodec codec : codecRegistry.getCodecs()) {
                if (codec instanceof MapperMediaTypeCodec) {
                    codecs.add(((MapperMediaTypeCodec) codec).cloneWithFeatures(jsonFeatures));
                } else {
                    codecs.add(codec);
                }
            }
            if (!codecRegistry.findCodec(MediaType.APPLICATION_JSON_TYPE).isPresent()) {
                codecs.add(createNewJsonCodec(this.beanContext, jsonFeatures));
            }
            client.setMediaTypeCodecRegistry(MediaTypeCodecRegistry.of(codecs));
        }
        return client;
    });
}
Also used : CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) ArrayList(java.util.ArrayList) LoadBalancer(io.micronaut.http.client.LoadBalancer) MapperMediaTypeCodec(io.micronaut.json.codec.MapperMediaTypeCodec) HttpClientException(io.micronaut.http.client.exceptions.HttpClientException) ProxyHttpClient(io.micronaut.http.client.ProxyHttpClient) HttpClient(io.micronaut.http.client.HttpClient) StreamingHttpClient(io.micronaut.http.client.StreamingHttpClient) JsonFeatures(io.micronaut.json.JsonFeatures) MediaTypeCodecRegistry(io.micronaut.http.codec.MediaTypeCodecRegistry) HttpClientConfiguration(io.micronaut.http.client.HttpClientConfiguration) MapperMediaTypeCodec(io.micronaut.json.codec.MapperMediaTypeCodec) MediaTypeCodec(io.micronaut.http.codec.MediaTypeCodec)

Example 4 with MediaTypeCodecRegistry

use of io.micronaut.http.codec.MediaTypeCodecRegistry in project micronaut-core by micronaut-projects.

the class DefaultHttpClient method connectWebSocket.

private <T> Flux<T> connectWebSocket(URI uri, MutableHttpRequest<?> request, Class<T> clientEndpointType, WebSocketBean<T> webSocketBean) {
    Bootstrap bootstrap = this.bootstrap.clone();
    if (webSocketBean == null) {
        webSocketBean = webSocketRegistry.getWebSocket(clientEndpointType);
    }
    WebSocketBean<T> finalWebSocketBean = webSocketBean;
    return Flux.create(emitter -> {
        SslContext sslContext = buildSslContext(uri);
        WebSocketVersion protocolVersion = finalWebSocketBean.getBeanDefinition().enumValue(ClientWebSocket.class, "version", WebSocketVersion.class).orElse(WebSocketVersion.V13);
        int maxFramePayloadLength = finalWebSocketBean.messageMethod().map(m -> m.intValue(OnMessage.class, "maxPayloadLength").orElse(65536)).orElse(65536);
        String subprotocol = finalWebSocketBean.getBeanDefinition().stringValue(ClientWebSocket.class, "subprotocol").orElse(StringUtils.EMPTY_STRING);
        RequestKey requestKey;
        try {
            requestKey = new RequestKey(uri);
        } catch (HttpClientException e) {
            emitter.error(e);
            return;
        }
        bootstrap.remoteAddress(requestKey.getHost(), requestKey.getPort());
        initBootstrapForProxy(bootstrap, sslContext != null, requestKey.getHost(), requestKey.getPort());
        bootstrap.handler(new HttpClientInitializer(sslContext, requestKey.getHost(), requestKey.getPort(), false, false, false, null) {

            @Override
            protected void addFinalHandler(ChannelPipeline pipeline) {
                pipeline.remove(ChannelPipelineCustomizer.HANDLER_HTTP_DECODER);
                ReadTimeoutHandler readTimeoutHandler = pipeline.get(ReadTimeoutHandler.class);
                if (readTimeoutHandler != null) {
                    pipeline.remove(readTimeoutHandler);
                }
                Optional<Duration> readIdleTime = configuration.getReadIdleTimeout();
                if (readIdleTime.isPresent()) {
                    Duration duration = readIdleTime.get();
                    if (!duration.isNegative()) {
                        pipeline.addLast(ChannelPipelineCustomizer.HANDLER_IDLE_STATE, new IdleStateHandler(duration.toMillis(), duration.toMillis(), duration.toMillis(), TimeUnit.MILLISECONDS));
                    }
                }
                final NettyWebSocketClientHandler webSocketHandler;
                try {
                    String scheme = (sslContext == null) ? "ws" : "wss";
                    URI webSocketURL = UriBuilder.of(uri).scheme(scheme).host(host).port(port).build();
                    MutableHttpHeaders headers = request.getHeaders();
                    HttpHeaders customHeaders = EmptyHttpHeaders.INSTANCE;
                    if (headers instanceof NettyHttpHeaders) {
                        customHeaders = ((NettyHttpHeaders) headers).getNettyHeaders();
                    }
                    if (StringUtils.isNotEmpty(subprotocol)) {
                        customHeaders.add("Sec-WebSocket-Protocol", subprotocol);
                    }
                    webSocketHandler = new NettyWebSocketClientHandler<>(request, finalWebSocketBean, WebSocketClientHandshakerFactory.newHandshaker(webSocketURL, protocolVersion, subprotocol, true, customHeaders, maxFramePayloadLength), requestBinderRegistry, mediaTypeCodecRegistry, emitter);
                    pipeline.addLast(WebSocketClientCompressionHandler.INSTANCE);
                    pipeline.addLast(ChannelPipelineCustomizer.HANDLER_MICRONAUT_WEBSOCKET_CLIENT, webSocketHandler);
                } catch (Throwable e) {
                    emitter.error(new WebSocketSessionException("Error opening WebSocket client session: " + e.getMessage(), e));
                }
            }
        });
        addInstrumentedListener(bootstrap.connect(), future -> {
            if (!future.isSuccess()) {
                emitter.error(future.cause());
            }
        });
    }, FluxSink.OverflowStrategy.ERROR);
}
Also used : AttributeKey(io.netty.util.AttributeKey) OrderUtil(io.micronaut.core.order.OrderUtil) Publishers(io.micronaut.core.async.publisher.Publishers) NoHostException(io.micronaut.http.client.exceptions.NoHostException) Processor(org.reactivestreams.Processor) JacksonDatabindMapper(io.micronaut.jackson.databind.JacksonDatabindMapper) ProxyHttpClient(io.micronaut.http.client.ProxyHttpClient) HttpProxyHandler(io.netty.handler.proxy.HttpProxyHandler) SseClient(io.micronaut.http.client.sse.SseClient) ChunkedWriteHandler(io.netty.handler.stream.ChunkedWriteHandler) HANDLER_IDLE_STATE(io.micronaut.http.netty.channel.ChannelPipelineCustomizer.HANDLER_IDLE_STATE) Internal(io.micronaut.core.annotation.Internal) NettyClientSslBuilder(io.micronaut.http.client.netty.ssl.NettyClientSslBuilder) Proxy(java.net.Proxy) InstantiationUtils(io.micronaut.core.reflect.InstantiationUtils) HttpStatus(io.micronaut.http.HttpStatus) Duration(java.time.Duration) CharsetUtil(io.netty.util.CharsetUtil) HANDLER_HTTP2_SETTINGS(io.micronaut.http.netty.channel.ChannelPipelineCustomizer.HANDLER_HTTP2_SETTINGS) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) ArgumentUtils(io.micronaut.core.util.ArgumentUtils) WebSocketClientHandshakerFactory(io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory) MapperMediaTypeCodec(io.micronaut.json.codec.MapperMediaTypeCodec) LoadBalancer(io.micronaut.http.client.LoadBalancer) SocketChannel(io.netty.channel.socket.SocketChannel) HttpClientErrorDecoder(io.micronaut.http.client.exceptions.HttpClientErrorDecoder) ResourceResolver(io.micronaut.core.io.ResourceResolver) ByteBufferFactory(io.micronaut.core.io.buffer.ByteBufferFactory) ReadTimeoutException(io.micronaut.http.client.exceptions.ReadTimeoutException) IdleStateEvent(io.netty.handler.timeout.IdleStateEvent) ChannelHealthChecker(io.netty.channel.pool.ChannelHealthChecker) StreamingInboundHttp2ToHttpAdapter(io.micronaut.http.netty.stream.StreamingInboundHttp2ToHttpAdapter) StandardCharsets(java.nio.charset.StandardCharsets) HttpFilterResolver(io.micronaut.http.filter.HttpFilterResolver) ClientFilterResolutionContext(io.micronaut.http.client.filter.ClientFilterResolutionContext) LineBasedFrameDecoder(io.netty.handler.codec.LineBasedFrameDecoder) AbstractChannelPoolHandler(io.netty.channel.pool.AbstractChannelPoolHandler) SslHandler(io.netty.handler.ssl.SslHandler) ReferenceCountUtil(io.netty.util.ReferenceCountUtil) MutableHttpRequest(io.micronaut.http.MutableHttpRequest) NettyWebSocketClientHandler(io.micronaut.http.client.netty.websocket.NettyWebSocketClientHandler) ChannelPoolMap(io.netty.channel.pool.ChannelPoolMap) MultipartDataFactory(io.micronaut.http.client.multipart.MultipartDataFactory) NettyByteBufferFactory(io.micronaut.buffer.netty.NettyByteBufferFactory) java.util(java.util) Disposable(reactor.core.Disposable) WebSocketBean(io.micronaut.websocket.context.WebSocketBean) OnMessage(io.micronaut.websocket.annotation.OnMessage) ContentLengthExceededException(io.micronaut.http.client.exceptions.ContentLengthExceededException) Supplier(java.util.function.Supplier) StreamedHttpResponse(io.micronaut.http.netty.stream.StreamedHttpResponse) NettyThreadFactory(io.micronaut.http.netty.channel.NettyThreadFactory) NettyHttpRequestBuilder(io.micronaut.http.netty.NettyHttpRequestBuilder) DefaultHttpClientConfiguration(io.micronaut.http.client.DefaultHttpClientConfiguration) NettyHttpHeaders(io.micronaut.http.netty.NettyHttpHeaders) Nullable(io.micronaut.core.annotation.Nullable) ByteBuffer(io.micronaut.core.io.buffer.ByteBuffer) JsonStreamMediaTypeCodec(io.micronaut.json.codec.JsonStreamMediaTypeCodec) Argument(io.micronaut.core.type.Argument) MultipartException(io.micronaut.http.multipart.MultipartException) ConversionService(io.micronaut.core.convert.ConversionService) ServerRequestContext(io.micronaut.http.context.ServerRequestContext) NOOP(io.micronaut.scheduling.instrument.InvocationInstrumenter.NOOP) MediaTypeCodecRegistry(io.micronaut.http.codec.MediaTypeCodecRegistry) Attribute(io.netty.util.Attribute) JsonNode(io.micronaut.json.tree.JsonNode) SslContext(io.netty.handler.ssl.SslContext) FileUpload(io.netty.handler.codec.http.multipart.FileUpload) Publisher(org.reactivestreams.Publisher) HttpClientConfiguration(io.micronaut.http.client.HttpClientConfiguration) Mono(reactor.core.publisher.Mono) IOException(java.io.IOException) NettyHttpResponseBuilder(io.micronaut.http.netty.NettyHttpResponseBuilder) File(java.io.File) AbstractNettyHttpRequest(io.micronaut.http.netty.AbstractNettyHttpRequest) SimpleChannelPool(io.netty.channel.pool.SimpleChannelPool) Bootstrap(io.netty.bootstrap.Bootstrap) Flux(reactor.core.publisher.Flux) WebSocketClientCompressionHandler(io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler) DEFAULT_SHUTDOWN_TIMEOUT_MILLISECONDS(io.micronaut.http.client.HttpClientConfiguration.DEFAULT_SHUTDOWN_TIMEOUT_MILLISECONDS) ChannelPipelineCustomizer(io.micronaut.http.netty.channel.ChannelPipelineCustomizer) ChannelPool(io.netty.channel.pool.ChannelPool) Instrumentation(io.micronaut.scheduling.instrument.Instrumentation) WebSocketClient(io.micronaut.websocket.WebSocketClient) Future(io.netty.util.concurrent.Future) DefaultThreadFactory(io.netty.util.concurrent.DefaultThreadFactory) ChannelPipelineListener(io.micronaut.http.netty.channel.ChannelPipelineListener) DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) SocketAddress(java.net.SocketAddress) HttpStreamsClientHandler(io.micronaut.http.netty.stream.HttpStreamsClientHandler) UriTemplate(io.micronaut.http.uri.UriTemplate) io.netty.handler.codec.http2(io.netty.handler.codec.http2) ByteBufAllocator(io.netty.buffer.ByteBufAllocator) URISyntaxException(java.net.URISyntaxException) DEFAULT_SHUTDOWN_QUIET_PERIOD_MILLISECONDS(io.micronaut.http.client.HttpClientConfiguration.DEFAULT_SHUTDOWN_QUIET_PERIOD_MILLISECONDS) ArrayUtils(io.micronaut.core.util.ArrayUtils) LoggerFactory(org.slf4j.LoggerFactory) TimeoutException(java.util.concurrent.TimeoutException) InvocationInstrumenter(io.micronaut.scheduling.instrument.InvocationInstrumenter) InvocationInstrumenterFactory(io.micronaut.scheduling.instrument.InvocationInstrumenterFactory) ClientFilterChain(io.micronaut.http.filter.ClientFilterChain) DefaultHttp2Content(io.micronaut.http.netty.stream.DefaultHttp2Content) Event(io.micronaut.http.sse.Event) Unpooled(io.netty.buffer.Unpooled) FixedChannelPool(io.netty.channel.pool.FixedChannelPool) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) MediaType(io.micronaut.http.MediaType) ReferenceCounted(io.micronaut.core.io.buffer.ReferenceCounted) JsonMapper(io.micronaut.json.JsonMapper) ApplicationProtocolNegotiationHandler(io.netty.handler.ssl.ApplicationProtocolNegotiationHandler) HttpResponse(io.micronaut.http.HttpResponse) ApplicationConfiguration(io.micronaut.runtime.ApplicationConfiguration) URI(java.net.URI) HttpClient(io.micronaut.http.client.HttpClient) HttpDataFactory(io.netty.handler.codec.http.multipart.HttpDataFactory) ThreadFactory(java.util.concurrent.ThreadFactory) RequestBinderRegistry(io.micronaut.http.bind.RequestBinderRegistry) MultipartBody(io.micronaut.http.client.multipart.MultipartBody) JsonMediaTypeCodec(io.micronaut.json.codec.JsonMediaTypeCodec) CodecException(io.micronaut.http.codec.CodecException) ReadTimeoutHandler(io.netty.handler.timeout.ReadTimeoutHandler) MutableHttpResponse(io.micronaut.http.MutableHttpResponse) MutableHttpHeaders(io.micronaut.http.MutableHttpHeaders) TooLongFrameException(io.netty.handler.codec.TooLongFrameException) InterfaceHttpData(io.netty.handler.codec.http.multipart.InterfaceHttpData) InetSocketAddress(java.net.InetSocketAddress) Collectors(java.util.stream.Collectors) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) StringUtils(io.micronaut.core.util.StringUtils) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) HttpClientFilter(io.micronaut.http.filter.HttpClientFilter) StreamedHttpRequest(io.micronaut.http.netty.stream.StreamedHttpRequest) io.netty.handler.codec.http(io.netty.handler.codec.http) StreamingHttpClient(io.micronaut.http.client.StreamingHttpClient) WebSocketSessionException(io.micronaut.websocket.exceptions.WebSocketSessionException) Type(java.net.Proxy.Type) Socks5ProxyHandler(io.netty.handler.proxy.Socks5ProxyHandler) ClientWebSocket(io.micronaut.websocket.annotation.ClientWebSocket) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) ClientServerContextFilter(io.micronaut.http.client.filters.ClientServerContextFilter) LoggingHandler(io.netty.handler.logging.LoggingHandler) UriBuilder(io.micronaut.http.uri.UriBuilder) HttpPostRequestEncoder(io.netty.handler.codec.http.multipart.HttpPostRequestEncoder) FluxSink(reactor.core.publisher.FluxSink) DefaultHttpDataFactory(io.netty.handler.codec.http.multipart.DefaultHttpDataFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HttpClientFilterResolver(io.micronaut.http.filter.HttpClientFilterResolver) Scheduler(reactor.core.scheduler.Scheduler) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) WebSocketBeanRegistry(io.micronaut.websocket.context.WebSocketBeanRegistry) BeanMap(io.micronaut.core.beans.BeanMap) NoopAddressResolverGroup(io.netty.resolver.NoopAddressResolverGroup) WebSocketVersion(io.netty.handler.codec.http.websocketx.WebSocketVersion) BlockingHttpClient(io.micronaut.http.client.BlockingHttpClient) ByteBuf(io.netty.buffer.ByteBuf) Charset(java.nio.charset.Charset) HttpClientException(io.micronaut.http.client.exceptions.HttpClientException) io.netty.channel(io.netty.channel) Schedulers(reactor.core.scheduler.Schedulers) HttpResponseWrapper(io.micronaut.http.HttpResponseWrapper) Subscriber(org.reactivestreams.Subscriber) MediaTypeCodec(io.micronaut.http.codec.MediaTypeCodec) Logger(org.slf4j.Logger) DefaultRequestBinderRegistry(io.micronaut.http.bind.DefaultRequestBinderRegistry) MalformedURLException(java.net.MalformedURLException) AnnotationMetadataResolver(io.micronaut.core.annotation.AnnotationMetadataResolver) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener) ApplicationProtocolNames(io.netty.handler.ssl.ApplicationProtocolNames) DefaultHttpClientFilterResolver(io.micronaut.http.client.filter.DefaultHttpClientFilterResolver) Http2Content(io.micronaut.http.netty.stream.Http2Content) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) NonNull(io.micronaut.core.annotation.NonNull) IdleStateHandler(io.netty.handler.timeout.IdleStateHandler) ByteBufUtil(io.netty.buffer.ByteBufUtil) EmptyByteBuf(io.netty.buffer.EmptyByteBuf) CollectionUtils(io.micronaut.core.util.CollectionUtils) Subscription(org.reactivestreams.Subscription) Closeable(java.io.Closeable) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) AbstractChannelPoolMap(io.netty.channel.pool.AbstractChannelPoolMap) JsonSubscriber(io.micronaut.http.netty.stream.JsonSubscriber) InputStream(java.io.InputStream) NettyHttpHeaders(io.micronaut.http.netty.NettyHttpHeaders) MutableHttpHeaders(io.micronaut.http.MutableHttpHeaders) OnMessage(io.micronaut.websocket.annotation.OnMessage) URI(java.net.URI) NettyWebSocketClientHandler(io.micronaut.http.client.netty.websocket.NettyWebSocketClientHandler) HttpClientException(io.micronaut.http.client.exceptions.HttpClientException) Bootstrap(io.netty.bootstrap.Bootstrap) SslContext(io.netty.handler.ssl.SslContext) Duration(java.time.Duration) NettyHttpHeaders(io.micronaut.http.netty.NettyHttpHeaders) WebSocketVersion(io.netty.handler.codec.http.websocketx.WebSocketVersion) WebSocketSessionException(io.micronaut.websocket.exceptions.WebSocketSessionException) IdleStateHandler(io.netty.handler.timeout.IdleStateHandler) ReadTimeoutHandler(io.netty.handler.timeout.ReadTimeoutHandler) ClientWebSocket(io.micronaut.websocket.annotation.ClientWebSocket) MutableHttpHeaders(io.micronaut.http.MutableHttpHeaders)

Example 5 with MediaTypeCodecRegistry

use of io.micronaut.http.codec.MediaTypeCodecRegistry in project micronaut-core by micronaut-projects.

the class DefaultHttpClient method addFullHttpResponseHandler.

@SuppressWarnings("MagicNumber")
private <O, E> void addFullHttpResponseHandler(io.micronaut.http.HttpRequest<?> request, Channel channel, boolean secure, ChannelPool channelPool, FluxSink<io.micronaut.http.HttpResponse<O>> emitter, Argument<O> bodyType, Argument<E> errorType) {
    ChannelPipeline pipeline = channel.pipeline();
    final SimpleChannelInboundHandler<FullHttpResponse> newHandler = new SimpleChannelInboundHandlerInstrumented<FullHttpResponse>(false) {

        AtomicBoolean complete = new AtomicBoolean(false);

        boolean keepAlive = true;

        @Override
        public boolean acceptInboundMessage(Object msg) {
            return msg instanceof FullHttpResponse && (secure || !discardH2cStream((HttpMessage) msg));
        }

        @Override
        protected void channelReadInstrumented(ChannelHandlerContext channelHandlerContext, FullHttpResponse fullResponse) {
            try {
                HttpResponseStatus status = fullResponse.status();
                int statusCode = status.code();
                HttpStatus httpStatus;
                try {
                    httpStatus = HttpStatus.valueOf(statusCode);
                } catch (IllegalArgumentException e) {
                    if (complete.compareAndSet(false, true)) {
                        if (!emitter.isCancelled()) {
                            emitter.error(e);
                        }
                    } else if (log.isWarnEnabled()) {
                        log.warn("Unsupported http status after handler completed: " + e.getMessage(), e);
                    }
                    return;
                }
                try {
                    HttpHeaders headers = fullResponse.headers();
                    if (log.isDebugEnabled()) {
                        log.debug("Received response {} from {}", status.code(), request.getUri());
                    }
                    if (log.isTraceEnabled()) {
                        traceHeaders(headers);
                        traceBody("Response", fullResponse.content());
                    }
                    // it is a redirect
                    if (statusCode > 300 && statusCode < 400 && configuration.isFollowRedirects() && headers.contains(HttpHeaderNames.LOCATION)) {
                        String location = headers.get(HttpHeaderNames.LOCATION);
                        final MutableHttpRequest<Object> redirectRequest;
                        if (statusCode == 307) {
                            redirectRequest = io.micronaut.http.HttpRequest.create(request.getMethod(), location);
                            request.getBody().ifPresent(redirectRequest::body);
                        } else {
                            redirectRequest = io.micronaut.http.HttpRequest.GET(location);
                        }
                        setRedirectHeaders(request, redirectRequest);
                        Flux<io.micronaut.http.HttpResponse<O>> redirectExchange = Flux.from(resolveRedirectURI(request, redirectRequest)).switchMap(buildExchangePublisher(request, redirectRequest, bodyType, errorType));
                        redirectExchange.defaultIfEmpty(io.micronaut.http.HttpResponse.notFound()).subscribe(oHttpResponse -> {
                            if (bodyType == null || !bodyType.isVoid()) {
                                emitter.next(oHttpResponse);
                            }
                            emitter.complete();
                        }, throwable -> {
                            if (!emitter.isCancelled()) {
                                emitter.error(throwable);
                            }
                        });
                        return;
                    }
                    if (statusCode == HttpStatus.NO_CONTENT.getCode()) {
                        // normalize the NO_CONTENT header, since http content aggregator adds it even if not present in the response
                        headers.remove(HttpHeaderNames.CONTENT_LENGTH);
                    }
                    boolean convertBodyWithBodyType = statusCode < 400 || (!DefaultHttpClient.this.configuration.isExceptionOnErrorStatus() && bodyType.equalsType(errorType));
                    FullNettyClientHttpResponse<O> response = new FullNettyClientHttpResponse<>(fullResponse, httpStatus, mediaTypeCodecRegistry, byteBufferFactory, bodyType, convertBodyWithBodyType);
                    if (complete.compareAndSet(false, true)) {
                        if (convertBodyWithBodyType) {
                            if (bodyType == null || !bodyType.isVoid()) {
                                emitter.next(response);
                            }
                            response.onComplete();
                            emitter.complete();
                        } else {
                            // error flow
                            try {
                                HttpClientResponseException clientError;
                                if (errorType != null && errorType != HttpClient.DEFAULT_ERROR_TYPE) {
                                    clientError = new HttpClientResponseException(status.reasonPhrase(), null, response, new HttpClientErrorDecoder() {

                                        @Override
                                        public Argument<?> getErrorType(MediaType mediaType) {
                                            return errorType;
                                        }
                                    });
                                } else {
                                    clientError = new HttpClientResponseException(status.reasonPhrase(), response);
                                }
                                try {
                                    if (!emitter.isCancelled()) {
                                        emitter.error(clientError);
                                    }
                                } finally {
                                    response.onComplete();
                                }
                            } catch (Throwable t) {
                                if (t instanceof HttpClientResponseException) {
                                    try {
                                        if (!emitter.isCancelled()) {
                                            emitter.error(t);
                                        }
                                    } finally {
                                        response.onComplete();
                                    }
                                } else {
                                    response.onComplete();
                                    FullNettyClientHttpResponse<Object> errorResponse = new FullNettyClientHttpResponse<>(fullResponse, httpStatus, mediaTypeCodecRegistry, byteBufferFactory, null, false);
                                    errorResponse.onComplete();
                                    HttpClientResponseException clientResponseError = new HttpClientResponseException("Error decoding HTTP error response body: " + t.getMessage(), t, errorResponse, null);
                                    if (!emitter.isCancelled()) {
                                        emitter.error(clientResponseError);
                                    }
                                }
                            }
                        }
                    }
                } catch (Throwable t) {
                    if (complete.compareAndSet(false, true)) {
                        if (t instanceof HttpClientResponseException) {
                            if (!emitter.isCancelled()) {
                                emitter.error(t);
                            }
                        } else {
                            FullNettyClientHttpResponse<Object> response = new FullNettyClientHttpResponse<>(fullResponse, httpStatus, mediaTypeCodecRegistry, byteBufferFactory, null, false);
                            HttpClientResponseException clientResponseError = new HttpClientResponseException("Error decoding HTTP response body: " + t.getMessage(), t, response, new HttpClientErrorDecoder() {

                                @Override
                                public Argument<?> getErrorType(MediaType mediaType) {
                                    return errorType;
                                }
                            });
                            try {
                                if (!emitter.isCancelled()) {
                                    emitter.error(clientResponseError);
                                }
                            } finally {
                                response.onComplete();
                            }
                        }
                    } else {
                        if (log.isWarnEnabled()) {
                            log.warn("Exception fired after handler completed: " + t.getMessage(), t);
                        }
                    }
                }
            } finally {
                if (fullResponse.refCnt() > 0) {
                    try {
                        ReferenceCountUtil.release(fullResponse);
                    } catch (Throwable e) {
                        if (log.isDebugEnabled()) {
                            log.debug("Failed to release response: {}", fullResponse);
                        }
                    }
                }
                if (!HttpUtil.isKeepAlive(fullResponse)) {
                    keepAlive = false;
                }
                pipeline.remove(this);
            }
        }

        @Override
        public void handlerRemoved(ChannelHandlerContext ctx) {
            if (channelPool != null) {
                if (readTimeoutMillis != null) {
                    ctx.pipeline().remove(ChannelPipelineCustomizer.HANDLER_READ_TIMEOUT);
                }
                final Channel ch = ctx.channel();
                if (!keepAlive) {
                    ch.closeFuture().addListener((future -> channelPool.release(ch)));
                } else {
                    channelPool.release(ch);
                }
            } else {
                // just close it to prevent any future reads without a handler registered
                ctx.close();
            }
        }

        @Override
        public void handlerAdded(ChannelHandlerContext ctx) {
            if (readTimeoutMillis != null) {
                if (httpVersion == io.micronaut.http.HttpVersion.HTTP_2_0) {
                    Http2SettingsHandler settingsHandler = (Http2SettingsHandler) ctx.pipeline().get(HANDLER_HTTP2_SETTINGS);
                    if (settingsHandler != null) {
                        addInstrumentedListener(settingsHandler.promise, future -> {
                            if (future.isSuccess()) {
                                pipeline.addBefore(ChannelPipelineCustomizer.HANDLER_HTTP2_CONNECTION, ChannelPipelineCustomizer.HANDLER_READ_TIMEOUT, new ReadTimeoutHandler(readTimeoutMillis, TimeUnit.MILLISECONDS));
                            }
                        });
                    } else {
                        pipeline.addBefore(ChannelPipelineCustomizer.HANDLER_HTTP2_CONNECTION, ChannelPipelineCustomizer.HANDLER_READ_TIMEOUT, new ReadTimeoutHandler(readTimeoutMillis, TimeUnit.MILLISECONDS));
                    }
                } else {
                    pipeline.addBefore(ChannelPipelineCustomizer.HANDLER_HTTP_CLIENT_CODEC, ChannelPipelineCustomizer.HANDLER_READ_TIMEOUT, new ReadTimeoutHandler(readTimeoutMillis, TimeUnit.MILLISECONDS));
                }
            }
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            try {
                if (complete.compareAndSet(false, true)) {
                    String message = cause.getMessage();
                    if (message == null) {
                        message = cause.getClass().getSimpleName();
                    }
                    if (log.isTraceEnabled()) {
                        log.trace("HTTP Client exception ({}) occurred for request : {} {}", message, request.getMethodName(), request.getUri());
                    }
                    if (cause instanceof TooLongFrameException) {
                        if (!emitter.isCancelled()) {
                            emitter.error(new ContentLengthExceededException(configuration.getMaxContentLength()));
                        }
                    } else if (cause instanceof io.netty.handler.timeout.ReadTimeoutException) {
                        if (!emitter.isCancelled()) {
                            emitter.error(ReadTimeoutException.TIMEOUT_EXCEPTION);
                        }
                    } else {
                        if (!emitter.isCancelled()) {
                            emitter.error(new HttpClientException("Error occurred reading HTTP response: " + message, cause));
                        }
                    }
                }
            } finally {
                keepAlive = false;
                pipeline.remove(this);
            }
        }
    };
    pipeline.addLast(ChannelPipelineCustomizer.HANDLER_MICRONAUT_FULL_HTTP_RESPONSE, newHandler);
}
Also used : AttributeKey(io.netty.util.AttributeKey) OrderUtil(io.micronaut.core.order.OrderUtil) Publishers(io.micronaut.core.async.publisher.Publishers) NoHostException(io.micronaut.http.client.exceptions.NoHostException) Processor(org.reactivestreams.Processor) JacksonDatabindMapper(io.micronaut.jackson.databind.JacksonDatabindMapper) ProxyHttpClient(io.micronaut.http.client.ProxyHttpClient) HttpProxyHandler(io.netty.handler.proxy.HttpProxyHandler) SseClient(io.micronaut.http.client.sse.SseClient) ChunkedWriteHandler(io.netty.handler.stream.ChunkedWriteHandler) HANDLER_IDLE_STATE(io.micronaut.http.netty.channel.ChannelPipelineCustomizer.HANDLER_IDLE_STATE) Internal(io.micronaut.core.annotation.Internal) NettyClientSslBuilder(io.micronaut.http.client.netty.ssl.NettyClientSslBuilder) Proxy(java.net.Proxy) InstantiationUtils(io.micronaut.core.reflect.InstantiationUtils) HttpStatus(io.micronaut.http.HttpStatus) Duration(java.time.Duration) CharsetUtil(io.netty.util.CharsetUtil) HANDLER_HTTP2_SETTINGS(io.micronaut.http.netty.channel.ChannelPipelineCustomizer.HANDLER_HTTP2_SETTINGS) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) ArgumentUtils(io.micronaut.core.util.ArgumentUtils) WebSocketClientHandshakerFactory(io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory) MapperMediaTypeCodec(io.micronaut.json.codec.MapperMediaTypeCodec) LoadBalancer(io.micronaut.http.client.LoadBalancer) SocketChannel(io.netty.channel.socket.SocketChannel) HttpClientErrorDecoder(io.micronaut.http.client.exceptions.HttpClientErrorDecoder) ResourceResolver(io.micronaut.core.io.ResourceResolver) ByteBufferFactory(io.micronaut.core.io.buffer.ByteBufferFactory) ReadTimeoutException(io.micronaut.http.client.exceptions.ReadTimeoutException) IdleStateEvent(io.netty.handler.timeout.IdleStateEvent) ChannelHealthChecker(io.netty.channel.pool.ChannelHealthChecker) StreamingInboundHttp2ToHttpAdapter(io.micronaut.http.netty.stream.StreamingInboundHttp2ToHttpAdapter) StandardCharsets(java.nio.charset.StandardCharsets) HttpFilterResolver(io.micronaut.http.filter.HttpFilterResolver) ClientFilterResolutionContext(io.micronaut.http.client.filter.ClientFilterResolutionContext) LineBasedFrameDecoder(io.netty.handler.codec.LineBasedFrameDecoder) AbstractChannelPoolHandler(io.netty.channel.pool.AbstractChannelPoolHandler) SslHandler(io.netty.handler.ssl.SslHandler) ReferenceCountUtil(io.netty.util.ReferenceCountUtil) MutableHttpRequest(io.micronaut.http.MutableHttpRequest) NettyWebSocketClientHandler(io.micronaut.http.client.netty.websocket.NettyWebSocketClientHandler) ChannelPoolMap(io.netty.channel.pool.ChannelPoolMap) MultipartDataFactory(io.micronaut.http.client.multipart.MultipartDataFactory) NettyByteBufferFactory(io.micronaut.buffer.netty.NettyByteBufferFactory) java.util(java.util) Disposable(reactor.core.Disposable) WebSocketBean(io.micronaut.websocket.context.WebSocketBean) OnMessage(io.micronaut.websocket.annotation.OnMessage) ContentLengthExceededException(io.micronaut.http.client.exceptions.ContentLengthExceededException) Supplier(java.util.function.Supplier) StreamedHttpResponse(io.micronaut.http.netty.stream.StreamedHttpResponse) NettyThreadFactory(io.micronaut.http.netty.channel.NettyThreadFactory) NettyHttpRequestBuilder(io.micronaut.http.netty.NettyHttpRequestBuilder) DefaultHttpClientConfiguration(io.micronaut.http.client.DefaultHttpClientConfiguration) NettyHttpHeaders(io.micronaut.http.netty.NettyHttpHeaders) Nullable(io.micronaut.core.annotation.Nullable) ByteBuffer(io.micronaut.core.io.buffer.ByteBuffer) JsonStreamMediaTypeCodec(io.micronaut.json.codec.JsonStreamMediaTypeCodec) Argument(io.micronaut.core.type.Argument) MultipartException(io.micronaut.http.multipart.MultipartException) ConversionService(io.micronaut.core.convert.ConversionService) ServerRequestContext(io.micronaut.http.context.ServerRequestContext) NOOP(io.micronaut.scheduling.instrument.InvocationInstrumenter.NOOP) MediaTypeCodecRegistry(io.micronaut.http.codec.MediaTypeCodecRegistry) Attribute(io.netty.util.Attribute) JsonNode(io.micronaut.json.tree.JsonNode) SslContext(io.netty.handler.ssl.SslContext) FileUpload(io.netty.handler.codec.http.multipart.FileUpload) Publisher(org.reactivestreams.Publisher) HttpClientConfiguration(io.micronaut.http.client.HttpClientConfiguration) Mono(reactor.core.publisher.Mono) IOException(java.io.IOException) NettyHttpResponseBuilder(io.micronaut.http.netty.NettyHttpResponseBuilder) File(java.io.File) AbstractNettyHttpRequest(io.micronaut.http.netty.AbstractNettyHttpRequest) SimpleChannelPool(io.netty.channel.pool.SimpleChannelPool) Bootstrap(io.netty.bootstrap.Bootstrap) Flux(reactor.core.publisher.Flux) WebSocketClientCompressionHandler(io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler) DEFAULT_SHUTDOWN_TIMEOUT_MILLISECONDS(io.micronaut.http.client.HttpClientConfiguration.DEFAULT_SHUTDOWN_TIMEOUT_MILLISECONDS) ChannelPipelineCustomizer(io.micronaut.http.netty.channel.ChannelPipelineCustomizer) ChannelPool(io.netty.channel.pool.ChannelPool) Instrumentation(io.micronaut.scheduling.instrument.Instrumentation) WebSocketClient(io.micronaut.websocket.WebSocketClient) Future(io.netty.util.concurrent.Future) DefaultThreadFactory(io.netty.util.concurrent.DefaultThreadFactory) ChannelPipelineListener(io.micronaut.http.netty.channel.ChannelPipelineListener) DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) SocketAddress(java.net.SocketAddress) HttpStreamsClientHandler(io.micronaut.http.netty.stream.HttpStreamsClientHandler) UriTemplate(io.micronaut.http.uri.UriTemplate) io.netty.handler.codec.http2(io.netty.handler.codec.http2) ByteBufAllocator(io.netty.buffer.ByteBufAllocator) URISyntaxException(java.net.URISyntaxException) DEFAULT_SHUTDOWN_QUIET_PERIOD_MILLISECONDS(io.micronaut.http.client.HttpClientConfiguration.DEFAULT_SHUTDOWN_QUIET_PERIOD_MILLISECONDS) ArrayUtils(io.micronaut.core.util.ArrayUtils) LoggerFactory(org.slf4j.LoggerFactory) TimeoutException(java.util.concurrent.TimeoutException) InvocationInstrumenter(io.micronaut.scheduling.instrument.InvocationInstrumenter) InvocationInstrumenterFactory(io.micronaut.scheduling.instrument.InvocationInstrumenterFactory) ClientFilterChain(io.micronaut.http.filter.ClientFilterChain) DefaultHttp2Content(io.micronaut.http.netty.stream.DefaultHttp2Content) Event(io.micronaut.http.sse.Event) Unpooled(io.netty.buffer.Unpooled) FixedChannelPool(io.netty.channel.pool.FixedChannelPool) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) MediaType(io.micronaut.http.MediaType) ReferenceCounted(io.micronaut.core.io.buffer.ReferenceCounted) JsonMapper(io.micronaut.json.JsonMapper) ApplicationProtocolNegotiationHandler(io.netty.handler.ssl.ApplicationProtocolNegotiationHandler) HttpResponse(io.micronaut.http.HttpResponse) ApplicationConfiguration(io.micronaut.runtime.ApplicationConfiguration) URI(java.net.URI) HttpClient(io.micronaut.http.client.HttpClient) HttpDataFactory(io.netty.handler.codec.http.multipart.HttpDataFactory) ThreadFactory(java.util.concurrent.ThreadFactory) RequestBinderRegistry(io.micronaut.http.bind.RequestBinderRegistry) MultipartBody(io.micronaut.http.client.multipart.MultipartBody) JsonMediaTypeCodec(io.micronaut.json.codec.JsonMediaTypeCodec) CodecException(io.micronaut.http.codec.CodecException) ReadTimeoutHandler(io.netty.handler.timeout.ReadTimeoutHandler) MutableHttpResponse(io.micronaut.http.MutableHttpResponse) MutableHttpHeaders(io.micronaut.http.MutableHttpHeaders) TooLongFrameException(io.netty.handler.codec.TooLongFrameException) InterfaceHttpData(io.netty.handler.codec.http.multipart.InterfaceHttpData) InetSocketAddress(java.net.InetSocketAddress) Collectors(java.util.stream.Collectors) NioEventLoopGroup(io.netty.channel.nio.NioEventLoopGroup) StringUtils(io.micronaut.core.util.StringUtils) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) HttpClientFilter(io.micronaut.http.filter.HttpClientFilter) StreamedHttpRequest(io.micronaut.http.netty.stream.StreamedHttpRequest) io.netty.handler.codec.http(io.netty.handler.codec.http) StreamingHttpClient(io.micronaut.http.client.StreamingHttpClient) WebSocketSessionException(io.micronaut.websocket.exceptions.WebSocketSessionException) Type(java.net.Proxy.Type) Socks5ProxyHandler(io.netty.handler.proxy.Socks5ProxyHandler) ClientWebSocket(io.micronaut.websocket.annotation.ClientWebSocket) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) ClientServerContextFilter(io.micronaut.http.client.filters.ClientServerContextFilter) LoggingHandler(io.netty.handler.logging.LoggingHandler) UriBuilder(io.micronaut.http.uri.UriBuilder) HttpPostRequestEncoder(io.netty.handler.codec.http.multipart.HttpPostRequestEncoder) FluxSink(reactor.core.publisher.FluxSink) DefaultHttpDataFactory(io.netty.handler.codec.http.multipart.DefaultHttpDataFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HttpClientFilterResolver(io.micronaut.http.filter.HttpClientFilterResolver) Scheduler(reactor.core.scheduler.Scheduler) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) WebSocketBeanRegistry(io.micronaut.websocket.context.WebSocketBeanRegistry) BeanMap(io.micronaut.core.beans.BeanMap) NoopAddressResolverGroup(io.netty.resolver.NoopAddressResolverGroup) WebSocketVersion(io.netty.handler.codec.http.websocketx.WebSocketVersion) BlockingHttpClient(io.micronaut.http.client.BlockingHttpClient) ByteBuf(io.netty.buffer.ByteBuf) Charset(java.nio.charset.Charset) HttpClientException(io.micronaut.http.client.exceptions.HttpClientException) io.netty.channel(io.netty.channel) Schedulers(reactor.core.scheduler.Schedulers) HttpResponseWrapper(io.micronaut.http.HttpResponseWrapper) Subscriber(org.reactivestreams.Subscriber) MediaTypeCodec(io.micronaut.http.codec.MediaTypeCodec) Logger(org.slf4j.Logger) DefaultRequestBinderRegistry(io.micronaut.http.bind.DefaultRequestBinderRegistry) MalformedURLException(java.net.MalformedURLException) AnnotationMetadataResolver(io.micronaut.core.annotation.AnnotationMetadataResolver) GenericFutureListener(io.netty.util.concurrent.GenericFutureListener) ApplicationProtocolNames(io.netty.handler.ssl.ApplicationProtocolNames) DefaultHttpClientFilterResolver(io.micronaut.http.client.filter.DefaultHttpClientFilterResolver) Http2Content(io.micronaut.http.netty.stream.Http2Content) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) NonNull(io.micronaut.core.annotation.NonNull) IdleStateHandler(io.netty.handler.timeout.IdleStateHandler) ByteBufUtil(io.netty.buffer.ByteBufUtil) EmptyByteBuf(io.netty.buffer.EmptyByteBuf) CollectionUtils(io.micronaut.core.util.CollectionUtils) Subscription(org.reactivestreams.Subscription) Closeable(java.io.Closeable) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) AbstractChannelPoolMap(io.netty.channel.pool.AbstractChannelPoolMap) JsonSubscriber(io.micronaut.http.netty.stream.JsonSubscriber) InputStream(java.io.InputStream) NettyHttpHeaders(io.micronaut.http.netty.NettyHttpHeaders) MutableHttpHeaders(io.micronaut.http.MutableHttpHeaders) TooLongFrameException(io.netty.handler.codec.TooLongFrameException) HttpClientException(io.micronaut.http.client.exceptions.HttpClientException) MediaType(io.micronaut.http.MediaType) HttpStatus(io.micronaut.http.HttpStatus) SocketChannel(io.netty.channel.socket.SocketChannel) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) StreamedHttpResponse(io.micronaut.http.netty.stream.StreamedHttpResponse) DefaultStreamedHttpResponse(io.micronaut.http.netty.stream.DefaultStreamedHttpResponse) HttpResponse(io.micronaut.http.HttpResponse) MutableHttpResponse(io.micronaut.http.MutableHttpResponse) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) HttpClientErrorDecoder(io.micronaut.http.client.exceptions.HttpClientErrorDecoder) ReadTimeoutHandler(io.netty.handler.timeout.ReadTimeoutHandler) ContentLengthExceededException(io.micronaut.http.client.exceptions.ContentLengthExceededException)

Aggregations

HttpClient (io.micronaut.http.client.HttpClient)4 HttpClientConfiguration (io.micronaut.http.client.HttpClientConfiguration)4 LoadBalancer (io.micronaut.http.client.LoadBalancer)4 ProxyHttpClient (io.micronaut.http.client.ProxyHttpClient)4 StreamingHttpClient (io.micronaut.http.client.StreamingHttpClient)4 MediaTypeCodec (io.micronaut.http.codec.MediaTypeCodec)4 MediaTypeCodecRegistry (io.micronaut.http.codec.MediaTypeCodecRegistry)4 NettyByteBufferFactory (io.micronaut.buffer.netty.NettyByteBufferFactory)3 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)3 AnnotationMetadataResolver (io.micronaut.core.annotation.AnnotationMetadataResolver)3 Internal (io.micronaut.core.annotation.Internal)3 NonNull (io.micronaut.core.annotation.NonNull)3 Nullable (io.micronaut.core.annotation.Nullable)3 Publishers (io.micronaut.core.async.publisher.Publishers)3 BeanMap (io.micronaut.core.beans.BeanMap)3 ConversionService (io.micronaut.core.convert.ConversionService)3 ResourceResolver (io.micronaut.core.io.ResourceResolver)3 ByteBuffer (io.micronaut.core.io.buffer.ByteBuffer)3 ByteBufferFactory (io.micronaut.core.io.buffer.ByteBufferFactory)3 ReferenceCounted (io.micronaut.core.io.buffer.ReferenceCounted)3