use of io.servicetalk.http.api.StreamingHttpConnectionFilter in project servicetalk by apple.
the class MalformedDataAfterHttpMessageTest method afterResponseNextClientRequestSucceeds.
@ParameterizedTest
@ValueSource(booleans = { true, false })
void afterResponseNextClientRequestSucceeds(boolean doOffloading) throws Exception {
Queue<ConnectionContext> contextQueue = new LinkedBlockingQueue<>();
ServerSocketChannel server = nettyServer(RESPONSE_MSG);
try (BlockingHttpClient client = stClientBuilder(server.localAddress()).executionStrategy(doOffloading ? defaultStrategy() : offloadNever()).appendClientFilter(new RetryingHttpRequesterFilter.Builder().retryOther((req, cause) -> ofConstantBackoffFullJitter(ofNanos(1), MAX_VALUE)).build()).appendConnectionFilter(connection -> new StreamingHttpConnectionFilter(connection) {
@Override
public Single<StreamingHttpResponse> request(final StreamingHttpRequest request) {
contextQueue.add(connectionContext());
return super.request(request);
}
}).buildBlocking()) {
validateClientResponse(client.request(client.get("/1")));
validateClientResponse(client.request(client.get("/2")));
ConnectionContext ctx1 = contextQueue.poll();
assertThat(ctx1, not(nullValue()));
// RetryingHttpRequesterFilter or AutoRetry may re-issue the request if a failure is seen locally. Verify
// the last connection (used for second request) is different from the first.
ConnectionContext ctx2 = null;
ConnectionContext tmp;
while ((tmp = contextQueue.poll()) != null) {
ctx2 = tmp;
}
assertThat(ctx2, not(nullValue()));
assertThat(ctx1, not(equalTo(ctx2)));
assertThat(contextQueue, empty());
} finally {
server.close().sync();
}
}
use of io.servicetalk.http.api.StreamingHttpConnectionFilter in project servicetalk by apple.
the class H2ConcurrencyControllerTest method setUp.
@BeforeEach
void setUp() throws Exception {
serverEventLoopGroup = createIoExecutor(1, "server-io").eventLoopGroup();
for (int i = 0; i < N_ITERATIONS; i++) {
latches[i] = new CountDownLatch(1);
}
AtomicBoolean secondAndMore = new AtomicBoolean();
serverAcceptorChannel = bindH2Server(serverEventLoopGroup, new ChannelInitializer<Http2StreamChannel>() {
@Override
protected void initChannel(Http2StreamChannel ch) {
// Respond only for the first request which is used to propagate MAX_CONCURRENT_STREAMS_VALUE
if (secondAndMore.compareAndSet(false, true)) {
ch.pipeline().addLast(new EchoHttp2Handler());
} else {
// Do not respond to any subsequent requests, only release the associated latch to notify the client
// that server received the request.
ch.pipeline().addLast(new SimpleChannelInboundHandler<Http2HeadersFrame>() {
@Override
protected void channelRead0(final ChannelHandlerContext ctx, final Http2HeadersFrame msg) {
String path = msg.headers().path().toString();
int i = parseInt(path.substring(1));
latches[i].countDown();
}
});
}
}
}, parentPipeline -> {
}, h2Builder -> {
h2Builder.initialSettings().maxConcurrentStreams(MAX_CONCURRENT_STREAMS_VALUE);
return h2Builder;
});
final HostAndPort serverAddress = of((InetSocketAddress) serverAcceptorChannel.localAddress());
client = forResolvedAddress(serverAddress).ioExecutor(CTX.ioExecutor()).executor(CTX.executor()).executionStrategy(defaultStrategy()).appendClientFilter(// All exceptions should be propagated
disableAutoRetries()).appendConnectionFilter(MulticastTransportEventsStreamingHttpConnectionFilter::new).appendConnectionFilter(connection -> new StreamingHttpConnectionFilter(connection) {
@Override
public Single<StreamingHttpResponse> request(StreamingHttpRequest request) {
return delegate().request(request).liftSync(subscriber -> new SingleSource.Subscriber<StreamingHttpResponse>() {
@Override
public void onSubscribe(final Cancellable cancellable) {
// Defer the cancel() signal to let the test thread start a new request
subscriber.onSubscribe(() -> CTX.executor().schedule(cancellable::cancel, ofMillis(100)));
}
@Override
public void onSuccess(@Nullable final StreamingHttpResponse result) {
subscriber.onSuccess(result);
}
@Override
public void onError(final Throwable t) {
subscriber.onError(t);
}
});
}
}).protocols(h2().enableFrameLogging("servicetalk-tests-h2-frame-logger", TRACE, () -> true).build()).build();
}
use of io.servicetalk.http.api.StreamingHttpConnectionFilter in project servicetalk by apple.
the class H2PriorKnowledgeFeatureParityTest method clientConnectionFilterAsyncContext.
@ParameterizedTest(name = "{displayName} [{index}] client={0}, h2PriorKnowledge={1}")
@MethodSource("clientExecutors")
void clientConnectionFilterAsyncContext(HttpTestExecutionStrategy strategy, boolean h2PriorKnowledge) throws Exception {
setUp(strategy, h2PriorKnowledge);
InetSocketAddress serverAddress = bindHttpEchoServer();
final Queue<Throwable> errorQueue = new ConcurrentLinkedQueue<>();
try (BlockingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).executionStrategy(clientExecutionStrategy).appendConnectionFilter(connection -> new StreamingHttpConnectionFilter(connection) {
@Override
public Single<StreamingHttpResponse> request(final StreamingHttpRequest request) {
return asyncContextTestRequest(errorQueue, delegate(), request);
}
}).buildBlocking()) {
final String responseBody = "foo";
HttpResponse response = client.request(client.post("/0").payloadBody(responseBody, textSerializerUtf8()));
assertEquals(responseBody, response.payloadBody(textSerializerUtf8()));
assertNoAsyncErrors(errorQueue);
}
}
use of io.servicetalk.http.api.StreamingHttpConnectionFilter in project servicetalk by apple.
the class ClientEffectiveStrategyTest method clientStrategy.
@ParameterizedTest(name = "API={0} builder={1} filter={2} LB={3} CF={4}")
@MethodSource("casesSupplier")
void clientStrategy(ClientType clientType, @Nullable final HttpExecutionStrategy builderStrategy, @Nullable final HttpExecutionStrategy filterStrategy, @Nullable final HttpExecutionStrategy lbStrategy, @Nullable final HttpExecutionStrategy cfStrategy) throws Exception {
HttpExecutionStrategy effectiveStrategy = computeClientExecutionStrategy(builderStrategy, filterStrategy, lbStrategy, cfStrategy);
SingleAddressHttpClientBuilder<HostAndPort, InetSocketAddress> clientBuilder = HttpClients.forSingleAddress(serverHostAndPort(context));
if (builderStrategy != null) {
clientBuilder.executionStrategy(builderStrategy);
}
ClientInvokingThreadRecorder invokingThreadsRecorder = new ClientInvokingThreadRecorder(clientType, effectiveStrategy);
clientBuilder.appendClientFilter(invokingThreadsRecorder);
if (null != filterStrategy) {
clientBuilder.appendClientFilter(new StreamingHttpClientFilterFactory() {
@Override
public StreamingHttpClientFilter create(final FilterableStreamingHttpClient client) {
return new StreamingHttpClientFilter(client) {
};
}
@Override
public HttpExecutionStrategy requiredOffloads() {
return filterStrategy;
}
});
}
if (null != lbStrategy) {
HttpLoadBalancerFactory<InetSocketAddress> lfFactory = DefaultHttpLoadBalancerFactory.Builder.from(new LoadBalancerFactoryImpl() {
@Override
public ExecutionStrategy requiredOffloads() {
return lbStrategy;
}
}).build();
clientBuilder.loadBalancerFactory(lfFactory);
}
if (null != cfStrategy) {
clientBuilder.appendConnectionFilter(new StreamingHttpConnectionFilterFactory() {
@Override
public StreamingHttpConnectionFilter create(final FilterableStreamingHttpConnection connection) {
return new StreamingHttpConnectionFilter(connection) {
};
}
@Override
public HttpExecutionStrategy requiredOffloads() {
return cfStrategy;
}
});
}
// Exercise the client
try (StreamingHttpClient client = clientBuilder.buildStreaming()) {
String responseBody = getResponse(clientType, client);
assertThat(responseBody, is(GREETING));
invokingThreadsRecorder.verifyOffloads();
}
}
use of io.servicetalk.http.api.StreamingHttpConnectionFilter in project servicetalk by apple.
the class RetryRequestWithNonRepeatablePayloadTest method setUp.
private void setUp(HttpProtocol protocol, TestPublisher<Buffer> payloadBody, Queue<Throwable> errors, boolean offloading) {
protocol(protocol.config);
ChannelOutboundHandler firstWriteHandler = new FailingFirstWriteHandler();
connectionFactoryFilter(ConnectionFactoryFilter.withStrategy(factory -> new DelegatingConnectionFactory<InetSocketAddress, FilterableStreamingHttpConnection>(factory) {
@Override
public Single<FilterableStreamingHttpConnection> newConnection(InetSocketAddress address, @Nullable TransportObserver observer) {
return delegate().newConnection(address, observer).map(c -> {
final Channel channel = ((NettyConnectionContext) c.connectionContext()).nettyChannel();
if (protocol == HTTP_1) {
// Insert right before HttpResponseDecoder to avoid seeing failed frames on wire logs
channel.pipeline().addBefore(HttpRequestEncoder.class.getSimpleName() + "#0", null, firstWriteHandler);
} else if (protocol == HTTP_2) {
// Insert right before Http2MultiplexHandler to avoid failing connection-level frames and
// seeing failed stream frames on frame/wire logs
channel.pipeline().addBefore(Http2MultiplexHandler.class.getSimpleName() + "#0", null, firstWriteHandler);
}
return new StreamingHttpConnectionFilter(c) {
@Override
public Single<StreamingHttpResponse> request(StreamingHttpRequest request) {
return delegate().request(request).whenOnError(t -> {
try {
assertThat("Unexpected exception type", t, instanceOf(RetryableException.class));
assertThat("Unexpected exception type", t.getCause(), instanceOf(DeliberateException.class));
assertThat("Unexpected subscribe to payload body", payloadBody.isSubscribed(), is(false));
} catch (Throwable error) {
errors.add(error);
}
});
}
};
});
}
}, ExecutionStrategy.offloadNone()));
setUp(offloading ? CACHED : IMMEDIATE, offloading ? CACHED_SERVER : IMMEDIATE);
}
Aggregations