private static HttpClient initHttpClient(ReactorResourceFactory resourceFactory) { ConnectionProvider provider = resourceFactory.getConnectionProvider(); LoopResources resources = resourceFactory.getLoopResources(); Assert.notNull(provider, "No ConnectionProvider: is ReactorResourceFactory not initialized yet?"); Assert.notNull(resources, "No LoopResources: is ReactorResourceFactory not initialized yet?"); return HttpClient.create(provider).tcpConfiguration(tcpClient -> tcpClient.runOn(resources)); }
/** * Simple constructor with the host and port to use to connect to. * <p>This constructor manages the lifecycle of the {@link TcpClient} and * underlying resources such as {@link ConnectionProvider}, * {@link LoopResources}, and {@link ChannelGroup}. * <p>For full control over the initialization and lifecycle of the * TcpClient, use {@link #ReactorNettyTcpClient(TcpClient, ReactorNettyCodec)}. * @param host the host to connect to * @param port the port to connect to * @param codec for encoding and decoding the input/output byte streams * @see org.springframework.messaging.simp.stomp.StompReactorNettyCodec */ public ReactorNettyTcpClient(String host, int port, ReactorNettyCodec<P> codec) { Assert.notNull(host, "host is required"); Assert.notNull(codec, "ReactorNettyCodec is required"); this.channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); this.loopResources = LoopResources.create("tcp-client-loop"); this.poolResources = ConnectionProvider.elastic("tcp-client-pool"); this.codec = codec; this.tcpClient = TcpClient.create(this.poolResources) .host(host).port(port) .runOn(this.loopResources, false) .doOnConnected(conn -> this.channelGroup.add(conn.channel())); }
@Override public HttpServer apply(HttpServer server) { try { return server.secure((contextSpec) -> { SslProvider.DefaultConfigurationSpec spec = contextSpec .sslContext(getContextBuilder()); if (this.http2 != null && this.http2.isEnabled()) { spec.defaultConfiguration(SslProvider.DefaultConfigurationType.H2); } }); } catch (Exception ex) { throw new IllegalStateException(ex); } }
/** * A variant of {@link #ReactorNettyTcpClient(String, int, ReactorNettyCodec)} * that still manages the lifecycle of the {@link TcpClient} and underlying * resources, but allows for direct configuration of other properties of the * client through a {@code Function<TcpClient, TcpClient>}. * @param clientConfigurer the configurer function * @param codec for encoding and decoding the input/output byte streams * @since 5.1.3 * @see org.springframework.messaging.simp.stomp.StompReactorNettyCodec */ public ReactorNettyTcpClient(Function<TcpClient, TcpClient> clientConfigurer, ReactorNettyCodec<P> codec) { Assert.notNull(codec, "ReactorNettyCodec is required"); this.channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); this.loopResources = LoopResources.create("tcp-client-loop"); this.poolResources = ConnectionProvider.elastic("tcp-client-pool"); this.codec = codec; this.tcpClient = clientConfigurer.apply(TcpClient .create(this.poolResources) .runOn(this.loopResources, false) .doOnConnected(conn -> this.channelGroup.add(conn.channel()))); }
private static WebClientProvider getWebClientProvider(ClientConfiguration clientConfiguration) { Duration connectTimeout = clientConfiguration.getConnectTimeout(); Duration soTimeout = clientConfiguration.getSocketTimeout(); TcpClient tcpClient = TcpClient.create(); if (!connectTimeout.isNegative()) { tcpClient = tcpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Math.toIntExact(connectTimeout.toMillis())); } if (!soTimeout.isNegative()) { tcpClient = tcpClient.doOnConnected(connection -> connection // .addHandlerLast(new ReadTimeoutHandler(soTimeout.toMillis(), TimeUnit.MILLISECONDS)) .addHandlerLast(new WriteTimeoutHandler(soTimeout.toMillis(), TimeUnit.MILLISECONDS))); } String scheme = "http"; HttpClient httpClient = HttpClient.from(tcpClient); if (clientConfiguration.useSsl()) { httpClient = httpClient.secure(sslConfig -> { Optional<SSLContext> sslContext = clientConfiguration.getSslContext(); sslContext.ifPresent(it -> sslConfig.sslContext(new JdkSslContext(it, true, ClientAuth.NONE))); }); scheme = "https"; } ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient); WebClientProvider provider = WebClientProvider.create(scheme, connector); return provider.withDefaultHeaders(clientConfiguration.getDefaultHeaders()); }
tcpClient = tcpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, properties.getConnectTimeout()); tcpClient = tcpClient.proxy(proxySpec -> { ProxyProvider.Builder builder = proxySpec .type(ProxyProvider.Proxy.HTTP) .host(proxy.getHost()); map.from(proxy::getPassword) .whenHasText() .to(password -> builder.password(s -> password)); map.from(proxy::getNonProxyHostsPattern) .whenHasText() sslContextSpec.sslContext(sslContextBuilder) .defaultConfiguration(ssl.getDefaultConfigurationType()) .handshakeTimeout(ssl.getHandshakeTimeout()) .closeNotifyFlushTimeout(ssl.getCloseNotifyFlushTimeout()) .closeNotifyReadTimeout(ssl.getCloseNotifyReadTimeout()); });
/** * Creates a new instance * * @param address the address to connect to * @return a new instance * @throws NullPointerException if {@code address} is {@code null} */ public static TcpClientTransport create(InetSocketAddress address) { Objects.requireNonNull(address, "address must not be null"); TcpClient tcpClient = TcpClient.create().addressSupplier(() -> address); return create(tcpClient); }
@Override public ListenableFuture<Void> connect(final TcpConnectionHandler<P> handler) { Assert.notNull(handler, "TcpConnectionHandler is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } Mono<Void> connectMono = this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnError(handler::afterConnectFailure) .then(); return new MonoToListenableFutureAdapter<>(connectMono); }
private HttpServer createHttpServer() { HttpServer server = HttpServer.create(); if (this.resourceFactory != null) { LoopResources resources = this.resourceFactory.getLoopResources(); Assert.notNull(resources, "No LoopResources: is ReactorResourceFactory not initialized yet?"); server = server.tcpConfiguration((tcpServer) -> tcpServer.runOn(resources) .addressSupplier(this::getListenAddress)); } else { server = server.tcpConfiguration( (tcpServer) -> tcpServer.addressSupplier(this::getListenAddress)); } if (getSsl() != null && getSsl().isEnabled()) { SslServerCustomizer sslServerCustomizer = new SslServerCustomizer(getSsl(), getHttp2(), getSslStoreProvider()); server = sslServerCustomizer.apply(server); } if (getCompression() != null && getCompression().getEnabled()) { CompressionCustomizer compressionCustomizer = new CompressionCustomizer( getCompression()); server = compressionCustomizer.apply(server); } server = server.protocol(listProtocols()).forwarded(this.useForwardHeaders); return applyCustomizers(server); }
@Before public void setup() { try { SslContext sslContext = SslContextBuilder.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE).build(); HttpClient httpClient = HttpClient.create().secure(ssl -> { ssl.sslContext(sslContext); }); ClientHttpConnector httpConnector = new ReactorClientHttpConnector( httpClient); baseUri = "https://localhost:" + port; this.webClient = WebClient.builder().clientConnector(httpConnector) .baseUrl(baseUri).build(); this.testClient = WebTestClient.bindToServer(httpConnector).baseUrl(baseUri).build(); } catch (SSLException e) { throw new RuntimeException(e); } }
@Override protected void initServer() { this.reactorHandler = createHttpHandlerAdapter(); this.reactorServer = reactor.netty.http.server.HttpServer.create() .tcpConfiguration(server -> server.host(getHost())) .port(getPort()); }
private ReactorClientHttpConnector initConnector() { if (bufferFactory instanceof NettyDataBufferFactory) { ByteBufAllocator allocator = ((NettyDataBufferFactory) bufferFactory).getByteBufAllocator(); return new ReactorClientHttpConnector(this.factory, httpClient -> httpClient.tcpConfiguration(tcpClient -> tcpClient.option(ChannelOption.ALLOCATOR, allocator))); } else { return new ReactorClientHttpConnector(); } }
private static WebClient.Builder createDefaultWebClient(Duration connectTimeout, Duration readTimeout) { HttpClient httpClient = HttpClient.create() .compress(true) .tcpConfiguration(tcp -> tcp.bootstrap(bootstrap -> bootstrap.option( ChannelOption.CONNECT_TIMEOUT_MILLIS, (int) connectTimeout.toMillis() )).observe((connection, newState) -> { if (ConnectionObserver.State.CONNECTED.equals(newState)) { connection.addHandlerLast(new ReadTimeoutHandler(readTimeout.toMillis(), TimeUnit.MILLISECONDS )); } })); ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient); return WebClient.builder().clientConnector(connector); } }
@Override protected void initServer() throws Exception { SelfSignedCertificate cert = new SelfSignedCertificate(); SslContextBuilder builder = SslContextBuilder.forServer(cert.certificate(), cert.privateKey()); this.reactorHandler = createHttpHandlerAdapter(); this.reactorServer = reactor.netty.http.server.HttpServer.create() .host(getHost()) .port(getPort()) .secure(spec -> spec.sslContext(builder).defaultConfiguration(DefaultConfigurationType.TCP)); }
private static HttpClient initHttpClient(ReactorResourceFactory resourceFactory) { ConnectionProvider provider = resourceFactory.getConnectionProvider(); LoopResources resources = resourceFactory.getLoopResources(); Assert.notNull(provider, "No ConnectionProvider: is ReactorResourceFactory not initialized yet?"); Assert.notNull(resources, "No LoopResources: is ReactorResourceFactory not initialized yet?"); return HttpClient.create(provider).tcpConfiguration(tcpClient -> tcpClient.runOn(resources)); }
@Override public ListenableFuture<Void> connect(TcpConnectionHandler<P> handler, ReconnectStrategy strategy) { Assert.notNull(handler, "TcpConnectionHandler is required"); Assert.notNull(strategy, "ReconnectStrategy is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } // Report first connect to the ListenableFuture MonoProcessor<Void> connectMono = MonoProcessor.create(); this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnNext(updateConnectMono(connectMono)) .doOnError(updateConnectMono(connectMono)) .doOnError(handler::afterConnectFailure) // report all connect failures to the handler .flatMap(Connection::onDispose) // post-connect issues .retryWhen(reconnectFunction(strategy)) .repeatWhen(reconnectFunction(strategy)) .subscribe(); return new MonoToListenableFutureAdapter<>(connectMono); }
@Override protected void initServer() { this.reactorHandler = createHttpHandlerAdapter(); this.reactorServer = reactor.netty.http.server.HttpServer.create() .tcpConfiguration(server -> server.host(getHost())) .port(getPort()); }