use of io.servicetalk.http.api.HttpExecutionContext in project servicetalk by apple.
the class DefaultMultiAddressUrlHttpClientBuilderTest method internalClientsUseDifferentExecutionContextWhenConfigured.
@Test
void internalClientsUseDifferentExecutionContextWhenConfigured() throws Exception {
HttpExecutionContext externalCtx = new HttpExecutionContextBuilder().ioExecutor(CTX.ioExecutor()).executor(CTX.executor()).bufferAllocator(PREFER_HEAP_ALLOCATOR).executionStrategy(offloadAll()).build();
HttpExecutionContext internalCtx = new HttpExecutionContextBuilder().ioExecutor(INTERNAL_CLIENT_CTX.ioExecutor()).executor(INTERNAL_CLIENT_CTX.executor()).bufferAllocator(PREFER_DIRECT_ALLOCATOR).executionStrategy(offloadNone()).build();
AtomicReference<HttpExecutionContext> actualInternalCtx = new AtomicReference<>();
try (ServerContext serverContext = HttpServers.forAddress(localAddress(0)).executionStrategy(offloadNone()).listenStreamingAndAwait((ctx, request, responseFactory) -> succeeded(responseFactory.ok()));
BlockingHttpClient blockingHttpClient = HttpClients.forMultiAddressUrl().initializer((scheme, address, builder) -> builder.executionStrategy(internalCtx.executionStrategy()).executor(internalCtx.executor()).ioExecutor(internalCtx.ioExecutor()).bufferAllocator(internalCtx.bufferAllocator()).appendClientFilter(client -> {
actualInternalCtx.set(client.executionContext());
return new StreamingHttpClientFilter(client) {
};
})).executor(externalCtx.executor()).ioExecutor(externalCtx.ioExecutor()).executionStrategy(externalCtx.executionStrategy()).bufferAllocator(externalCtx.bufferAllocator()).buildBlocking()) {
// Check external client
assertExecutionContext(externalCtx, blockingHttpClient.executionContext());
// Make a request to trigger the filter execution that extracts the execution context.
HttpResponse response = blockingHttpClient.request(blockingHttpClient.get("http://" + serverHostAndPort(serverContext)));
assertThat(response.status(), is(OK));
// Check internal client
assertExecutionContext(internalCtx, actualInternalCtx.get());
}
}
use of io.servicetalk.http.api.HttpExecutionContext in project servicetalk by apple.
the class DefaultPartitionedHttpClientBuilder method buildStreaming.
@Override
public StreamingHttpClient buildStreaming() {
final HttpExecutionContext executionContext = executionContextBuilder.build();
BiIntFunction<Throwable, ? extends Completable> sdRetryStrategy = serviceDiscovererRetryStrategy;
if (sdRetryStrategy == null) {
sdRetryStrategy = retryWithConstantBackoffDeltaJitter(__ -> true, SD_RETRY_STRATEGY_INIT_DURATION, SD_RETRY_STRATEGY_JITTER, executionContext.executor());
}
final 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
final SingleAddressHttpClientBuilder<U, R> builder = requireNonNull(builderFactory.get());
builder.serviceDiscoverer(sd);
setExecutionContext(builder, executionContext);
if (clientInitializer != null) {
clientInitializer.initialize(pa, builder);
}
return builder.buildStreaming();
};
final Publisher<PartitionedServiceDiscovererEvent<R>> psdEvents = psd.discover(address).flatMapConcatIterable(identity());
final HttpHeadersFactory headersFactory = this.headersFactory;
final DefaultPartitionedStreamingHttpClientFilter<U, R> partitionedClient = new DefaultPartitionedStreamingHttpClientFilter<>(psdEvents, serviceDiscoveryMaxQueueSize, clientFactory, partitionAttributesBuilderFactory, new DefaultStreamingHttpRequestResponseFactory(executionContext.bufferAllocator(), headersFactory != null ? headersFactory : DefaultHttpHeadersFactory.INSTANCE, HTTP_1_1), executionContext, partitionMapFactory);
LOGGER.debug("Partitioned client created with base strategy {}", executionContext.executionStrategy());
return new FilterableClientToClient(partitionedClient, executionContext.executionStrategy());
}
use of io.servicetalk.http.api.HttpExecutionContext 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 builderStrategy = 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(builderStrategy);
if (builderStrategy != defaultStrategy() && builderStrategy.missing(computedStrategy) != offloadNone()) {
LOGGER.info("Client for {} created with the builder strategy {} but resulting computed strategy is " + "{}. One of the filters enforces additional offloading. To find out what filter is " + "it, enable debug level logging for {}.", targetAddress(ctx), builderStrategy, computedStrategy, ClientStrategyInfluencerChainBuilder.class);
} else if (builderStrategy == computedStrategy) {
LOGGER.debug("Client for {} created with the execution strategy {}.", targetAddress(ctx), computedStrategy);
} else {
LOGGER.debug("Client for {} created with the builder strategy {}, resulting computed strategy is {}.", targetAddress(ctx), builderStrategy, computedStrategy);
}
return new FilterableClientToClient(currClientFilterFactory != null ? currClientFilterFactory.create(lbClient, lb.eventStream(), ctx.sdStatus) : lbClient, computedStrategy);
} catch (final Throwable t) {
closeOnException.closeAsync().subscribe();
throw t;
}
}
use of io.servicetalk.http.api.HttpExecutionContext in project servicetalk by apple.
the class TimeoutHttpServiceFilterTest method applyFilter.
private static Single<StreamingHttpResponse> applyFilter(TimeoutHttpServiceFilter filterFactory, final HttpExecutionStrategy strategy, final Single<StreamingHttpResponse> responseSingle) {
HttpExecutionContext executionContext = new DefaultHttpExecutionContext(DEFAULT_ALLOCATOR, IO_EXECUTOR, EXECUTOR, strategy);
HttpServiceContext serviceContext = mock(HttpServiceContext.class);
when(serviceContext.executionContext()).thenReturn(executionContext);
StreamingHttpService service = mock(StreamingHttpService.class);
when(service.handle(any(), any(), any())).thenReturn(responseSingle);
StreamingHttpServiceFilter filter = filterFactory.create(service);
return filter.handle(serviceContext, mock(StreamingHttpRequest.class), mock(StreamingHttpResponseFactory.class));
}
use of io.servicetalk.http.api.HttpExecutionContext in project servicetalk by apple.
the class BasicAuthHttpServiceFilterTest method beforeClass.
@BeforeAll
static void beforeClass() {
HttpExecutionContext ec = mock(HttpExecutionContext.class);
when(ec.bufferAllocator()).thenReturn(DEFAULT_ALLOCATOR);
when(CONN_CTX.executionContext()).thenReturn(ec);
}
Aggregations