Search in sources :

Example 6 with FilterableStreamingHttpClient

use of io.servicetalk.http.api.FilterableStreamingHttpClient in project servicetalk by apple.

the class DefaultSingleAddressHttpClientBuilder method buildStreaming.

private static <U, R> StreamingHttpClient buildStreaming(final HttpClientBuildContext<U, R> ctx) {
    final ReadOnlyHttpClientConfig roConfig = ctx.httpConfig().asReadOnly();
    final HttpExecutionContext executionContext = ctx.builder.executionContextBuilder.build();
    if (roConfig.h2Config() != null && roConfig.hasProxy()) {
        throw new IllegalStateException("Proxying is not yet supported with HTTP/2");
    }
    // Track resources that potentially need to be closed when an exception is thrown during buildStreaming
    final CompositeCloseable closeOnException = newCompositeCloseable();
    try {
        final Publisher<? extends Collection<? extends ServiceDiscovererEvent<R>>> sdEvents = ctx.serviceDiscoverer(executionContext).discover(ctx.address());
        ConnectionFactoryFilter<R, FilterableStreamingHttpConnection> connectionFactoryFilter = ctx.builder.connectionFactoryFilter;
        ExecutionStrategy connectionFactoryStrategy = ctx.builder.strategyComputation.buildForConnectionFactory();
        final SslContext sslContext = roConfig.tcpConfig().sslContext();
        if (roConfig.hasProxy() && sslContext != null) {
            assert roConfig.connectAddress() != null;
            ConnectionFactoryFilter<R, FilterableStreamingHttpConnection> proxy = new ProxyConnectConnectionFactoryFilter<>(roConfig.connectAddress());
            connectionFactoryFilter = proxy.append(connectionFactoryFilter);
            connectionFactoryStrategy = connectionFactoryStrategy.merge(proxy.requiredOffloads());
        }
        final HttpExecutionStrategy executionStrategy = executionContext.executionStrategy();
        // closed by the LoadBalancer
        final ConnectionFactory<R, LoadBalancedStreamingHttpConnection> connectionFactory;
        final StreamingHttpRequestResponseFactory reqRespFactory = defaultReqRespFactory(roConfig, executionContext.bufferAllocator());
        if (roConfig.isH2PriorKnowledge()) {
            H2ProtocolConfig h2Config = roConfig.h2Config();
            assert h2Config != null;
            connectionFactory = new H2LBHttpConnectionFactory<>(roConfig, executionContext, ctx.builder.connectionFilterFactory, reqRespFactory, connectionFactoryStrategy, connectionFactoryFilter, ctx.builder.loadBalancerFactory::toLoadBalancedConnection);
        } else if (roConfig.tcpConfig().preferredAlpnProtocol() != null) {
            H1ProtocolConfig h1Config = roConfig.h1Config();
            H2ProtocolConfig h2Config = roConfig.h2Config();
            connectionFactory = new AlpnLBHttpConnectionFactory<>(roConfig, executionContext, ctx.builder.connectionFilterFactory, new AlpnReqRespFactoryFunc(executionContext.bufferAllocator(), h1Config == null ? null : h1Config.headersFactory(), h2Config == null ? null : h2Config.headersFactory()), connectionFactoryStrategy, connectionFactoryFilter, ctx.builder.loadBalancerFactory::toLoadBalancedConnection);
        } else {
            H1ProtocolConfig h1Config = roConfig.h1Config();
            assert h1Config != null;
            connectionFactory = new PipelinedLBHttpConnectionFactory<>(roConfig, executionContext, ctx.builder.connectionFilterFactory, reqRespFactory, connectionFactoryStrategy, connectionFactoryFilter, ctx.builder.loadBalancerFactory::toLoadBalancedConnection);
        }
        final LoadBalancer<LoadBalancedStreamingHttpConnection> lb = closeOnException.prepend(ctx.builder.loadBalancerFactory.newLoadBalancer(targetAddress(ctx), sdEvents, connectionFactory));
        ContextAwareStreamingHttpClientFilterFactory currClientFilterFactory = ctx.builder.clientFilterFactory;
        if (roConfig.hasProxy() && sslContext == null) {
            // If we're talking to a proxy over http (not https), rewrite the request-target to absolute-form, as
            // specified by the RFC: https://tools.ietf.org/html/rfc7230#section-5.3.2
            currClientFilterFactory = appendFilter(currClientFilterFactory, ctx.builder.proxyAbsoluteAddressFilterFactory());
        }
        if (ctx.builder.addHostHeaderFallbackFilter) {
            currClientFilterFactory = appendFilter(currClientFilterFactory, new HostHeaderHttpRequesterFilter(ctx.builder.hostToCharSequenceFunction.apply(ctx.builder.address)));
        }
        FilterableStreamingHttpClient lbClient = closeOnException.prepend(new LoadBalancedStreamingHttpClient(executionContext, lb, reqRespFactory));
        if (ctx.builder.retryingHttpRequesterFilter == null) {
            ctx.builder.retryingHttpRequesterFilter = DEFAULT_AUTO_RETRIES;
            currClientFilterFactory = appendFilter(currClientFilterFactory, ctx.builder.retryingHttpRequesterFilter);
        }
        HttpExecutionStrategy computedStrategy = ctx.builder.strategyComputation.buildForClient(executionStrategy);
        LOGGER.debug("Client for {} created with base strategy {} → computed strategy {}", targetAddress(ctx), executionStrategy, computedStrategy);
        return new FilterableClientToClient(currClientFilterFactory != null ? currClientFilterFactory.create(lbClient, lb.eventStream(), ctx.sdStatus) : lbClient, computedStrategy);
    } catch (final Throwable t) {
        closeOnException.closeAsync().subscribe();
        throw t;
    }
}
Also used : CompositeCloseable(io.servicetalk.concurrent.api.CompositeCloseable) AsyncCloseables.newCompositeCloseable(io.servicetalk.concurrent.api.AsyncCloseables.newCompositeCloseable) FilterableStreamingHttpClient(io.servicetalk.http.api.FilterableStreamingHttpClient) StreamingHttpRequestResponseFactory(io.servicetalk.http.api.StreamingHttpRequestResponseFactory) DefaultStreamingHttpRequestResponseFactory(io.servicetalk.http.api.DefaultStreamingHttpRequestResponseFactory) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) ExecutionStrategy(io.servicetalk.transport.api.ExecutionStrategy) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) SslContext(io.netty.handler.ssl.SslContext) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext)

Example 7 with FilterableStreamingHttpClient

use of io.servicetalk.http.api.FilterableStreamingHttpClient in project servicetalk by apple.

the class DefaultPartitionedHttpClientBuilder method buildStreaming.

@Override
public StreamingHttpClient buildStreaming() {
    final HttpClientBuildContext<U, R> buildContext = builderTemplate.copyBuildCtx();
    final HttpExecutionContext executionContext = buildContext.builder.build().executionContext();
    BiIntFunction<Throwable, ? extends Completable> sdRetryStrategy = serviceDiscovererRetryStrategy;
    if (sdRetryStrategy == null) {
        sdRetryStrategy = retryWithConstantBackoffDeltaJitter(__ -> true, SD_RETRY_STRATEGY_INIT_DURATION, SD_RETRY_STRATEGY_JITTER, executionContext.executor());
    }
    ServiceDiscoverer<U, R, PartitionedServiceDiscovererEvent<R>> psd = new DefaultSingleAddressHttpClientBuilder.RetryingServiceDiscoverer<>(serviceDiscoverer, sdRetryStrategy);
    final PartitionedClientFactory<U, R, FilterableStreamingHttpClient> clientFactory = (pa, sd) -> {
        // build new context, user may have changed anything on the builder from the filter
        DefaultSingleAddressHttpClientBuilder<U, R> builder = buildContext.builder.copyBuildCtx().builder;
        builder.serviceDiscoverer(sd);
        clientFilterFunction.configureForPartition(pa, builder);
        if (clientInitializer != null) {
            clientInitializer.initialize(pa, builder);
        }
        return builder.buildStreaming();
    };
    final Publisher<PartitionedServiceDiscovererEvent<R>> psdEvents = psd.discover(buildContext.address()).flatMapConcatIterable(identity());
    DefaultPartitionedStreamingHttpClientFilter<U, R> partitionedClient = new DefaultPartitionedStreamingHttpClientFilter<>(psdEvents, serviceDiscoveryMaxQueueSize, clientFactory, partitionAttributesBuilderFactory, defaultReqRespFactory(buildContext.httpConfig().asReadOnly(), executionContext.bufferAllocator()), executionContext, partitionMapFactory);
    HttpExecutionStrategy computedStrategy = buildContext.builder.computeChainStrategy(executionContext.executionStrategy());
    LOGGER.debug("Client created with base strategy {} → computed strategy {}", executionContext.executionStrategy(), computedStrategy);
    return new FilterableClientToClient(partitionedClient, computedStrategy);
}
Also used : FilterableStreamingHttpClient(io.servicetalk.http.api.FilterableStreamingHttpClient) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) HttpRequestMethod(io.servicetalk.http.api.HttpRequestMethod) Publisher(io.servicetalk.concurrent.api.Publisher) PartitionMapFactory(io.servicetalk.client.api.partition.PartitionMapFactory) LoggerFactory(org.slf4j.LoggerFactory) ClientGroup(io.servicetalk.client.api.ClientGroup) Function(java.util.function.Function) SD_RETRY_STRATEGY_JITTER(io.servicetalk.http.netty.DefaultSingleAddressHttpClientBuilder.SD_RETRY_STRATEGY_JITTER) FilterableReservedStreamingHttpConnection(io.servicetalk.http.api.FilterableReservedStreamingHttpConnection) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) SD_RETRY_STRATEGY_INIT_DURATION(io.servicetalk.http.netty.DefaultSingleAddressHttpClientBuilder.SD_RETRY_STRATEGY_INIT_DURATION) DefaultSingleAddressHttpClientBuilder.defaultReqRespFactory(io.servicetalk.http.netty.DefaultSingleAddressHttpClientBuilder.defaultReqRespFactory) Objects.requireNonNull(java.util.Objects.requireNonNull) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) Executor(io.servicetalk.concurrent.api.Executor) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) Nullable(javax.annotation.Nullable) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext) RetryStrategies.retryWithConstantBackoffDeltaJitter(io.servicetalk.concurrent.api.RetryStrategies.retryWithConstantBackoffDeltaJitter) PartitionedClientFactory(io.servicetalk.client.api.internal.DefaultPartitionedClientGroup.PartitionedClientFactory) HttpClientBuildContext(io.servicetalk.http.netty.DefaultSingleAddressHttpClientBuilder.HttpClientBuildContext) Logger(org.slf4j.Logger) UnknownPartitionException(io.servicetalk.client.api.partition.UnknownPartitionException) PartitionAttributesBuilder(io.servicetalk.client.api.partition.PartitionAttributesBuilder) ListenableAsyncCloseable(io.servicetalk.concurrent.api.ListenableAsyncCloseable) PartitionedHttpClientBuilder(io.servicetalk.http.api.PartitionedHttpClientBuilder) StreamingHttpRequestResponseFactory(io.servicetalk.http.api.StreamingHttpRequestResponseFactory) Single.defer(io.servicetalk.concurrent.api.Single.defer) Single(io.servicetalk.concurrent.api.Single) Completable(io.servicetalk.concurrent.api.Completable) ServiceDiscoverer(io.servicetalk.client.api.ServiceDiscoverer) PartitionedServiceDiscovererEvent(io.servicetalk.client.api.partition.PartitionedServiceDiscovererEvent) HttpRequestMetaData(io.servicetalk.http.api.HttpRequestMetaData) IoExecutor(io.servicetalk.transport.api.IoExecutor) PartitionAttributes(io.servicetalk.client.api.partition.PartitionAttributes) ClosedPartitionException(io.servicetalk.client.api.partition.ClosedPartitionException) BufferAllocator(io.servicetalk.buffer.api.BufferAllocator) DefaultPartitionedClientGroup(io.servicetalk.client.api.internal.DefaultPartitionedClientGroup) PowerSetPartitionMapFactory(io.servicetalk.client.api.internal.partition.PowerSetPartitionMapFactory) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) Single.failed(io.servicetalk.concurrent.api.Single.failed) Function.identity(java.util.function.Function.identity) AsyncCloseables.emptyAsyncCloseable(io.servicetalk.concurrent.api.AsyncCloseables.emptyAsyncCloseable) ReservedStreamingHttpConnection(io.servicetalk.http.api.ReservedStreamingHttpConnection) BiIntFunction(io.servicetalk.concurrent.api.BiIntFunction) PartitionHttpClientBuilderConfigurator(io.servicetalk.http.api.PartitionHttpClientBuilderConfigurator) SD_RETRY_STRATEGY_JITTER(io.servicetalk.http.netty.DefaultSingleAddressHttpClientBuilder.SD_RETRY_STRATEGY_JITTER) PartitionedServiceDiscovererEvent(io.servicetalk.client.api.partition.PartitionedServiceDiscovererEvent) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext) FilterableStreamingHttpClient(io.servicetalk.http.api.FilterableStreamingHttpClient) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy)

Aggregations

FilterableStreamingHttpClient (io.servicetalk.http.api.FilterableStreamingHttpClient)7 HttpExecutionContext (io.servicetalk.http.api.HttpExecutionContext)4 HttpExecutionStrategy (io.servicetalk.http.api.HttpExecutionStrategy)4 FilterableStreamingHttpConnection (io.servicetalk.http.api.FilterableStreamingHttpConnection)3 AsyncCloseables.newCompositeCloseable (io.servicetalk.concurrent.api.AsyncCloseables.newCompositeCloseable)2 Completable (io.servicetalk.concurrent.api.Completable)2 CompositeCloseable (io.servicetalk.concurrent.api.CompositeCloseable)2 TestPublisher (io.servicetalk.concurrent.api.TestPublisher)2 HttpRequestMetaData (io.servicetalk.http.api.HttpRequestMetaData)2 StreamingHttpClient (io.servicetalk.http.api.StreamingHttpClient)2 StreamingHttpRequestResponseFactory (io.servicetalk.http.api.StreamingHttpRequestResponseFactory)2 Test (org.junit.jupiter.api.Test)2 SslContext (io.netty.handler.ssl.SslContext)1 Buffer (io.servicetalk.buffer.api.Buffer)1 BufferAllocator (io.servicetalk.buffer.api.BufferAllocator)1 DEFAULT_ALLOCATOR (io.servicetalk.buffer.netty.BufferAllocators.DEFAULT_ALLOCATOR)1 ClientGroup (io.servicetalk.client.api.ClientGroup)1 LOAD_BALANCER_READY_EVENT (io.servicetalk.client.api.LoadBalancerReadyEvent.LOAD_BALANCER_READY_EVENT)1 NoAvailableHostException (io.servicetalk.client.api.NoAvailableHostException)1 RetryableConnectException (io.servicetalk.client.api.RetryableConnectException)1