use of io.servicetalk.transport.api.ServerContext 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.transport.api.ServerContext in project servicetalk by apple.
the class DefaultSingleAddressHttpClientBuilderTest method hostToCharSequenceFunction.
private static void hostToCharSequenceFunction(String hostNamePrefix, String hostName, String hostNameSuffix, @Nullable Integer port) throws Exception {
try (ServerContext serverCtx = HttpServers.forAddress(localAddress(0)).sslConfig(new ServerSslConfigBuilder(DefaultTestCerts::loadServerPem, DefaultTestCerts::loadServerKey).build()).listenBlockingAndAwait((ctx, request, responseFactory) -> responseFactory.ok());
BlockingHttpClient client = new DefaultSingleAddressHttpClientBuilder<>(hostNamePrefix + hostName + hostNameSuffix + (port == null ? "" : port), GlobalDnsServiceDiscoverer.mappingServiceDiscoverer(u -> serverCtx.listenAddress())).sslConfig(new ClientSslConfigBuilder(DefaultTestCerts::loadServerCAPem).hostnameVerificationAlgorithm("").build()).buildBlocking()) {
ReservedBlockingHttpConnection conn = client.reserveConnection(client.get("/"));
try {
SSLSession sslSession = conn.connectionContext().sslSession();
assertNotNull(sslSession);
assertThat(sslSession.getPeerHost(), startsWith(hostName));
InetSocketAddress socketAddress = (InetSocketAddress) conn.connectionContext().remoteAddress();
assertEquals(socketAddress.getPort(), sslSession.getPeerPort());
} finally {
conn.release();
}
}
}
use of io.servicetalk.transport.api.ServerContext in project servicetalk by apple.
the class ConnectionAcceptorOffloadingTest method testAcceptorOffloading.
@ParameterizedTest
@ValueSource(booleans = { false, true })
void testAcceptorOffloading(boolean offload) throws Exception {
AtomicReference<Boolean> offloaded = new AtomicReference<>();
ConnectionAcceptorFactory factory = ConnectionAcceptorFactory.withStrategy(original -> context -> {
boolean isIoThread = IoThreadFactory.IoThread.currentThreadIsIoThread();
offloaded.set(!isIoThread);
return original.accept(context);
}, offload ? ConnectExecutionStrategy.offloadAll() : ConnectExecutionStrategy.offloadNone());
try (ServerContext server = HttpServers.forPort(0).appendConnectionAcceptorFilter(factory).listenAndAwait(this::helloWorld)) {
SocketAddress serverAddress = server.listenAddress();
try (BlockingHttpClient client = HttpClients.forResolvedAddress(serverAddress).buildBlocking()) {
HttpResponse response = client.request(client.get("/sayHello"));
assertThat("unexpected status", response.status(), is(HttpResponseStatus.OK));
}
}
assertThat("factory was not invoked", offloaded.get(), is(notNullValue()));
assertThat("incorrect offloading", offloaded.get(), is(offload));
}
use of io.servicetalk.transport.api.ServerContext in project servicetalk by apple.
the class ConnectionFactoryOffloadingTest method testFactoryOffloading.
@ParameterizedTest(name = "offload={0} httpStrategy={1}")
@MethodSource("testCases")
void testFactoryOffloading(boolean offload, HttpExecutionStrategy httpStrategy) throws Exception {
AtomicReference<Thread> factoryThread = new AtomicReference<>();
Thread appThread = Thread.currentThread();
try (ServerContext server = HttpServers.forPort(0).listenAndAwait(this::helloWorld)) {
SocketAddress serverAddress = server.listenAddress();
ConnectionFactoryFilter<SocketAddress, FilterableStreamingHttpConnection> factory = ConnectionFactoryFilter.withStrategy(original -> new ConnectionFactory<SocketAddress, FilterableStreamingHttpConnection>() {
private final ListenableAsyncCloseable close = emptyAsyncCloseable();
@Override
public Single<FilterableStreamingHttpConnection> newConnection(final SocketAddress socketAddress, @Nullable final ContextMap context, @Nullable final TransportObserver observer) {
factoryThread.set(Thread.currentThread());
return original.newConnection(socketAddress, context, observer);
}
@Override
public Completable onClose() {
return close.onClose();
}
@Override
public Completable closeAsync() {
return close.closeAsync();
}
@Override
public Completable closeAsyncGracefully() {
return close.closeAsyncGracefully();
}
}, new ConnectAndHttpExecutionStrategy(offload ? ConnectExecutionStrategy.offloadAll() : ConnectExecutionStrategy.offloadNone(), httpStrategy));
try (HttpClient client = HttpClients.forResolvedAddress(serverAddress).appendConnectionFactoryFilter(factory).build()) {
assertThat(client.executionContext().executionStrategy().missing(httpStrategy), is(HttpExecutionStrategies.offloadNone()));
Single<HttpResponse> single = client.request(client.get("/sayHello"));
HttpResponse response = single.toFuture().get();
assertThat("unexpected status", response.status(), is(HttpResponseStatus.OK));
}
}
assertTrue((offload && !IoThreadFactory.IoThread.isIoThread(factoryThread.get())) || (!offload && factoryThread.get() == appThread), "incorrect offloading, offload=" + offload + " thread=" + factoryThread.get());
}
use of io.servicetalk.transport.api.ServerContext in project servicetalk by apple.
the class ConsumeRequestPayloadOnResponsePathTest method test.
private void test(final BiFunction<Single<StreamingHttpResponse>, StreamingHttpRequest, Single<StreamingHttpResponse>> consumeRequestPayload) throws Exception {
try (ServerContext serverContext = HttpServers.forAddress(localAddress(0)).appendServiceFilter(service -> new StreamingHttpServiceFilter(service) {
@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
return consumeRequestPayload.apply(delegate().handle(ctx, request, responseFactory), request);
}
}).listenStreamingAndAwait((ctx, request, responseFactory) -> {
final StreamingHttpResponse response = responseFactory.ok().addHeader(TRAILER, X_TOTAL_LENGTH).payloadBody(from("Response\n", "Payload\n", "Body\n"), appSerializerUtf8FixLen()).transform(new TrailersTransformer<AtomicInteger, Buffer>() {
@Override
public AtomicInteger newState() {
return new AtomicInteger();
}
@Override
public Buffer accept(final AtomicInteger total, final Buffer chunk) {
total.addAndGet(chunk.readableBytes());
return chunk;
}
@Override
public HttpHeaders payloadComplete(final AtomicInteger total, final HttpHeaders trailers) {
trailers.add(X_TOTAL_LENGTH, String.valueOf(total.get()));
return trailers;
}
@Override
public HttpHeaders catchPayloadFailure(final AtomicInteger __, final Throwable ___, final HttpHeaders trailers) {
return trailers;
}
});
return succeeded(response);
})) {
HttpResponse response;
try (BlockingHttpClient client = HttpClients.forSingleAddress(AddressUtils.serverHostAndPort(serverContext)).buildBlocking()) {
response = client.request(client.post("/").payloadBody(EXPECTED_REQUEST_PAYLOAD, textSerializerUtf8()));
serverLatch.await();
}
assertThat(response.status(), is(OK));
assertThat("Request payload body might be consumed by someone else", errorRef.get(), is(nullValue()));
assertThat(receivedPayload.toString(), is(EXPECTED_REQUEST_PAYLOAD));
assertThat(response.headers().contains(TRAILER, X_TOTAL_LENGTH), is(true));
assertThat(response.trailers().contains(X_TOTAL_LENGTH), is(true));
CharSequence trailerLength = response.trailers().get(X_TOTAL_LENGTH);
assertNotNull(trailerLength);
assertThat("Unexpected response payload: '" + response.payloadBody().toString(UTF_8) + "'", trailerLength.toString(), is(Integer.toString(response.payloadBody().readableBytes())));
}
}
Aggregations