Search in sources :

Example 6 with FilterableStreamingHttpConnection

use of io.servicetalk.http.api.FilterableStreamingHttpConnection 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();
    }
}
Also used : FilterableStreamingHttpClient(io.servicetalk.http.api.FilterableStreamingHttpClient) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) BlockingStreamingHttpClient(io.servicetalk.http.api.BlockingStreamingHttpClient) InetSocketAddress(java.net.InetSocketAddress) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) StreamingHttpConnectionFilterFactory(io.servicetalk.http.api.StreamingHttpConnectionFilterFactory) StreamingHttpClientFilterFactory(io.servicetalk.http.api.StreamingHttpClientFilterFactory) AddressUtils.serverHostAndPort(io.servicetalk.transport.netty.internal.AddressUtils.serverHostAndPort) HostAndPort(io.servicetalk.transport.api.HostAndPort) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) StreamingHttpConnectionFilter(io.servicetalk.http.api.StreamingHttpConnectionFilter) FilterableStreamingHttpClient(io.servicetalk.http.api.FilterableStreamingHttpClient) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 7 with FilterableStreamingHttpConnection

use of io.servicetalk.http.api.FilterableStreamingHttpConnection 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;
    }
}
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) HostHeaderHttpRequesterFilter(io.servicetalk.http.utils.HostHeaderHttpRequesterFilter)

Example 8 with FilterableStreamingHttpConnection

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

the class H2PriorKnowledgeFeatureParityTest method clientRespectsSettingsFrame.

@ParameterizedTest(name = "{displayName} [{index}] client={0}, h2PriorKnowledge={1}")
@MethodSource("clientExecutors")
void clientRespectsSettingsFrame(HttpTestExecutionStrategy strategy, boolean h2PriorKnowledge) throws Exception {
    setUp(strategy, h2PriorKnowledge);
    assumeTrue(h2PriorKnowledge, "Only HTTP/2 supports SETTINGS frames");
    int expectedMaxConcurrent = 1;
    BlockingQueue<FilterableStreamingHttpConnection> connectionQueue = new LinkedBlockingQueue<>();
    BlockingQueue<Publisher<? extends ConsumableEvent<Integer>>> maxConcurrentPubQueue = new LinkedBlockingQueue<>();
    AtomicReference<Channel> serverParentChannelRef = new AtomicReference<>();
    CountDownLatch serverChannelLatch = new CountDownLatch(1);
    CountDownLatch serverSettingsAckLatch = new CountDownLatch(2);
    serverAcceptorChannel = bindH2Server(serverEventLoopGroup, new ChannelInitializer<Channel>() {

        @Override
        protected void initChannel(final Channel ch) {
            ch.pipeline().addLast(new EchoHttp2Handler());
        }
    }, parentPipeline -> parentPipeline.addLast(new ChannelInboundHandlerAdapter() {

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            if (serverParentChannelRef.compareAndSet(null, ctx.channel())) {
                serverChannelLatch.countDown();
            }
            super.channelActive(ctx);
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if (msg instanceof Http2SettingsAckFrame) {
                serverSettingsAckLatch.countDown();
            }
            super.channelRead(ctx, msg);
        }
    }), identity());
    InetSocketAddress serverAddress = (InetSocketAddress) serverAcceptorChannel.localAddress();
    try (StreamingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).executionStrategy(clientExecutionStrategy).appendConnectionFilter(conn -> new TestConnectionFilter(conn, connectionQueue, maxConcurrentPubQueue)).buildStreaming()) {
        Processor<Buffer, Buffer> requestPayload = newProcessor();
        client.request(client.post("/0").payloadBody(fromSource(requestPayload))).toFuture().get();
        serverChannelLatch.await();
        Channel serverParentChannel = serverParentChannelRef.get();
        serverParentChannel.writeAndFlush(new DefaultHttp2SettingsFrame(new Http2Settings().maxConcurrentStreams(expectedMaxConcurrent))).sync();
        Iterator<? extends ConsumableEvent<Integer>> maxItr = maxConcurrentPubQueue.take().toIterable().iterator();
        // Verify that the initial maxConcurrency value is the default number
        assertThat("No initial maxConcurrency value", maxItr.hasNext(), is(true));
        ConsumableEvent<Integer> next = maxItr.next();
        assertThat(next, is(notNullValue()));
        assertThat("First event is not the default", next.event(), is(SMALLEST_MAX_CONCURRENT_STREAMS));
        // We previously made a request, and intentionally didn't complete the request body. We want to verify
        // that we have received the SETTINGS frame reducing the total number of streams to 1.
        assertThat("No maxConcurrency value received", maxItr.hasNext(), is(true));
        next = maxItr.next();
        assertThat(next, is(notNullValue()));
        assertThat("maxConcurrency did not change to the expected value", next.event(), is(expectedMaxConcurrent));
        // Wait for a server to receive a settings ack
        serverSettingsAckLatch.await();
        // After this point we want to issue a new request and verify that client selects a new connection.
        Processor<Buffer, Buffer> requestPayload2 = newProcessor();
        client.request(client.post("/1").payloadBody(fromSource(requestPayload2))).toFuture().get();
        // We expect 2 connections to be created.
        assertNotSame(connectionQueue.take(), connectionQueue.take());
        requestPayload.onComplete();
        requestPayload2.onComplete();
    }
}
Also used : TestUtils.assertNoAsyncErrors(io.servicetalk.test.resources.TestUtils.assertNoAsyncErrors) UnaryOperator.identity(java.util.function.UnaryOperator.identity) ChannelInboundHandlerAdapter(io.netty.channel.ChannelInboundHandlerAdapter) SingleSource(io.servicetalk.concurrent.SingleSource) StreamingHttpServiceFilterFactory(io.servicetalk.http.api.StreamingHttpServiceFilterFactory) UnaryOperator(java.util.function.UnaryOperator) LogLevel(io.servicetalk.logging.api.LogLevel) DefaultHttp2DataFrame(io.netty.handler.codec.http2.DefaultHttp2DataFrame) Disabled(org.junit.jupiter.api.Disabled) Matchers.hasItems(org.hamcrest.Matchers.hasItems) SourceAdapters.fromSource(io.servicetalk.concurrent.api.SourceAdapters.fromSource) H2StreamResetException(io.servicetalk.http.netty.NettyHttp2ExceptionUtils.H2StreamResetException) AsyncContext(io.servicetalk.concurrent.api.AsyncContext) HttpRequest(io.servicetalk.http.api.HttpRequest) Assumptions.assumeFalse(org.junit.jupiter.api.Assumptions.assumeFalse) Matchers.nullValue(org.hamcrest.Matchers.nullValue) PROTOCOL_ERROR(io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR) HttpCookiePair(io.servicetalk.http.api.HttpCookiePair) DefaultHttp2ResetFrame(io.netty.handler.codec.http2.DefaultHttp2ResetFrame) EXPECT(io.servicetalk.http.api.HttpHeaderNames.EXPECT) BlockingHttpClient(io.servicetalk.http.api.BlockingHttpClient) PrintWriter(java.io.PrintWriter) Matchers.notNullValue(org.hamcrest.Matchers.notNullValue) DefaultHttp2SettingsFrame(io.netty.handler.codec.http2.DefaultHttp2SettingsFrame) HttpClients.forSingleAddress(io.servicetalk.http.netty.HttpClients.forSingleAddress) HttpResponse(io.servicetalk.http.api.HttpResponse) Http2SettingsAckFrame(io.netty.handler.codec.http2.Http2SettingsAckFrame) TRANSFER_ENCODING(io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING) POST(io.servicetalk.http.api.HttpRequestMethod.POST) BlockingQueue(java.util.concurrent.BlockingQueue) ChannelPipeline(io.netty.channel.ChannelPipeline) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) StatelessTrailersTransformer(io.servicetalk.http.api.StatelessTrailersTransformer) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) StreamingHttpConnectionFilter(io.servicetalk.http.api.StreamingHttpConnectionFilter) Arguments(org.junit.jupiter.params.provider.Arguments) Assertions.assertNotSame(org.junit.jupiter.api.Assertions.assertNotSame) Http2HeadersFrame(io.netty.handler.codec.http2.Http2HeadersFrame) UPGRADE(io.servicetalk.http.api.HttpHeaderNames.UPGRADE) CountDownLatch(java.util.concurrent.CountDownLatch) HttpSetCookie(io.servicetalk.http.api.HttpSetCookie) Buffer(io.servicetalk.buffer.api.Buffer) Stream(java.util.stream.Stream) Http2Headers(io.netty.handler.codec.http2.Http2Headers) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) COOKIE(io.servicetalk.http.api.HttpHeaderNames.COOKIE) Matchers.is(org.hamcrest.Matchers.is) CONTENT_TYPE(io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) Processor(io.servicetalk.concurrent.PublisherSource.Processor) BuilderUtils.serverChannel(io.servicetalk.transport.netty.internal.BuilderUtils.serverChannel) TRAILER(io.netty.handler.codec.http.HttpHeaderNames.TRAILER) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) HttpHeaders(io.servicetalk.http.api.HttpHeaders) ConsumableEvent(io.servicetalk.client.api.ConsumableEvent) StreamingHttpRequester(io.servicetalk.http.api.StreamingHttpRequester) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) ArrayList(java.util.ArrayList) EMPTY_BUFFER(io.servicetalk.buffer.api.EmptyBuffer.EMPTY_BUFFER) MAX_CONCURRENCY(io.servicetalk.http.api.HttpEventKey.MAX_CONCURRENCY) HeaderUtils.isTransferEncodingChunked(io.servicetalk.http.api.HeaderUtils.isTransferEncodingChunked) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) Processors(io.servicetalk.concurrent.api.Processors) BiConsumer(java.util.function.BiConsumer) Assumptions.assumeTrue(org.junit.jupiter.api.Assumptions.assumeTrue) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) AddressUtils.serverHostAndPort(io.servicetalk.transport.netty.internal.AddressUtils.serverHostAndPort) Matchers.contentEqualTo(io.servicetalk.buffer.api.Matchers.contentEqualTo) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Nullable(javax.annotation.Nullable) CHUNKED(io.servicetalk.http.api.HttpHeaderValues.CHUNKED) SMALLEST_MAX_CONCURRENT_STREAMS(io.netty.handler.codec.http2.Http2CodecUtil.SMALLEST_MAX_CONCURRENT_STREAMS) DEFAULT(io.servicetalk.http.netty.HttpTestExecutionStrategy.DEFAULT) Single(io.servicetalk.concurrent.api.Single) StringWriter(java.io.StringWriter) Completable(io.servicetalk.concurrent.api.Completable) DefaultHttp2HeadersFrame(io.netty.handler.codec.http2.DefaultHttp2HeadersFrame) IOException(java.io.IOException) ReservedBlockingHttpConnection(io.servicetalk.http.api.ReservedBlockingHttpConnection) OK(io.servicetalk.http.api.HttpResponseStatus.OK) GET(io.servicetalk.http.api.HttpRequestMethod.GET) Channel(io.netty.channel.Channel) Http2Settings(io.netty.handler.codec.http2.Http2Settings) AfterEach(org.junit.jupiter.api.AfterEach) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) String.valueOf(java.lang.String.valueOf) Completable.completed(io.servicetalk.concurrent.api.Completable.completed) Http2MultiplexHandler(io.netty.handler.codec.http2.Http2MultiplexHandler) HttpHeaderNames(io.netty.handler.codec.http.HttpHeaderNames) HttpResponseStatus(io.servicetalk.http.api.HttpResponseStatus) HostAndPort(io.servicetalk.transport.api.HostAndPort) HttpRequestMethod(io.servicetalk.http.api.HttpRequestMethod) Matchers.emptyString(org.hamcrest.Matchers.emptyString) Http2FrameCodecBuilder(io.netty.handler.codec.http2.Http2FrameCodecBuilder) Key.newKey(io.servicetalk.context.api.ContextMap.Key.newKey) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Http2DataFrame(io.netty.handler.codec.http2.Http2DataFrame) CONNECTION(io.servicetalk.http.api.HttpHeaderNames.CONNECTION) MethodSource(org.junit.jupiter.params.provider.MethodSource) ChannelDuplexHandler(io.netty.channel.ChannelDuplexHandler) ChannelInitializer(io.netty.channel.ChannelInitializer) PublisherSource(io.servicetalk.concurrent.PublisherSource) CONTENT_LENGTH(io.servicetalk.http.api.HttpHeaderNames.CONTENT_LENGTH) InetSocketAddress(java.net.InetSocketAddress) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) HttpEventKey(io.servicetalk.http.api.HttpEventKey) Test(org.junit.jupiter.api.Test) List(java.util.List) ContextMap(io.servicetalk.context.api.ContextMap) DelegatingConnectionAcceptor(io.servicetalk.transport.api.DelegatingConnectionAcceptor) Matchers.equalTo(org.hamcrest.Matchers.equalTo) Writer(java.io.Writer) Queue(java.util.Queue) CONTINUE(io.servicetalk.http.api.HttpHeaderValues.CONTINUE) ConcurrentLinkedQueue(java.util.concurrent.ConcurrentLinkedQueue) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Publisher(io.servicetalk.concurrent.api.Publisher) Http2Exception(io.servicetalk.http.api.Http2Exception) AtomicReference(java.util.concurrent.atomic.AtomicReference) StreamingHttpServiceFilter(io.servicetalk.http.api.StreamingHttpServiceFilter) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) HttpMetaData(io.servicetalk.http.api.HttpMetaData) HttpProtocolConfigs.h1Default(io.servicetalk.http.netty.HttpProtocolConfigs.h1Default) HttpProtocolConfigs.h2Default(io.servicetalk.http.netty.HttpProtocolConfigs.h2Default) HttpSerializers.textSerializerUtf8(io.servicetalk.http.api.HttpSerializers.textSerializerUtf8) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) NettyConnectionContext(io.servicetalk.transport.netty.internal.NettyConnectionContext) DELIBERATE_EXCEPTION(io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION) HttpServerBuilder(io.servicetalk.http.api.HttpServerBuilder) ConnectionContext(io.servicetalk.transport.api.ConnectionContext) KEEP_ALIVE(io.servicetalk.http.api.HttpHeaderValues.KEEP_ALIVE) INTERNAL_SERVER_ERROR(io.servicetalk.http.api.HttpResponseStatus.INTERNAL_SERVER_ERROR) AddressUtils.localAddress(io.servicetalk.transport.netty.internal.AddressUtils.localAddress) EventLoopGroup(io.netty.channel.EventLoopGroup) ServerContext(io.servicetalk.transport.api.ServerContext) Iterator(java.util.Iterator) EXPECTATION_FAILED(io.servicetalk.http.api.HttpResponseStatus.EXPECTATION_FAILED) NettyIoExecutors.createIoExecutor(io.servicetalk.transport.netty.internal.NettyIoExecutors.createIoExecutor) UTF_8(java.nio.charset.StandardCharsets.UTF_8) Processors.newPublisherProcessor(io.servicetalk.concurrent.api.Processors.newPublisherProcessor) Consumer(java.util.function.Consumer) Matchers.emptyIterable(org.hamcrest.Matchers.emptyIterable) PROXY_CONNECTION(io.servicetalk.http.netty.H2ToStH1Utils.PROXY_CONNECTION) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) NO_OFFLOAD(io.servicetalk.http.netty.HttpTestExecutionStrategy.NO_OFFLOAD) ServerBootstrap(io.netty.bootstrap.ServerBootstrap) ChannelHandler(io.netty.channel.ChannelHandler) SET_COOKIE(io.servicetalk.http.api.HttpHeaderNames.SET_COOKIE) DefaultHttpCookiePair(io.servicetalk.http.api.DefaultHttpCookiePair) DefaultHttp2Headers(io.netty.handler.codec.http2.DefaultHttp2Headers) Http2SettingsAckFrame(io.netty.handler.codec.http2.Http2SettingsAckFrame) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) InetSocketAddress(java.net.InetSocketAddress) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) ConsumableEvent(io.servicetalk.client.api.ConsumableEvent) ChannelInitializer(io.netty.channel.ChannelInitializer) Http2Settings(io.netty.handler.codec.http2.Http2Settings) Buffer(io.servicetalk.buffer.api.Buffer) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) DefaultHttp2SettingsFrame(io.netty.handler.codec.http2.DefaultHttp2SettingsFrame) BuilderUtils.serverChannel(io.servicetalk.transport.netty.internal.BuilderUtils.serverChannel) Channel(io.netty.channel.Channel) AtomicReference(java.util.concurrent.atomic.AtomicReference) Publisher(io.servicetalk.concurrent.api.Publisher) CountDownLatch(java.util.concurrent.CountDownLatch) H2StreamResetException(io.servicetalk.http.netty.NettyHttp2ExceptionUtils.H2StreamResetException) IOException(java.io.IOException) Http2Exception(io.servicetalk.http.api.Http2Exception) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ChannelInboundHandlerAdapter(io.netty.channel.ChannelInboundHandlerAdapter) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 9 with FilterableStreamingHttpConnection

use of io.servicetalk.http.api.FilterableStreamingHttpConnection 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 ContextMap context, @Nullable TransportObserver observer) {
            return delegate().newConnection(address, context, 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);
}
Also used : ChannelOutboundHandler(io.netty.channel.ChannelOutboundHandler) TestUtils.assertNoAsyncErrors(io.servicetalk.test.resources.TestUtils.assertNoAsyncErrors) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) TestPublisher(io.servicetalk.concurrent.api.TestPublisher) DeliberateException(io.servicetalk.concurrent.internal.DeliberateException) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) Sharable(io.netty.channel.ChannelHandler.Sharable) ArrayList(java.util.ArrayList) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ChannelPromise(io.netty.channel.ChannelPromise) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) ExecutionStrategy(io.servicetalk.transport.api.ExecutionStrategy) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) NettyConnectionContext(io.servicetalk.transport.netty.internal.NettyConnectionContext) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) DelegatingConnectionFactory(io.servicetalk.client.api.DelegatingConnectionFactory) DELIBERATE_EXCEPTION(io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION) Nullable(javax.annotation.Nullable) CACHED_SERVER(io.servicetalk.http.netty.AbstractNettyHttpServerTest.ExecutorSupplier.CACHED_SERVER) MethodSource(org.junit.jupiter.params.provider.MethodSource) IMMEDIATE(io.servicetalk.http.netty.AbstractNettyHttpServerTest.ExecutorSupplier.IMMEDIATE) ChannelOutboundHandlerAdapter(io.netty.channel.ChannelOutboundHandlerAdapter) ChannelOutboundHandler(io.netty.channel.ChannelOutboundHandler) Single(io.servicetalk.concurrent.api.Single) Collection(java.util.Collection) ConnectionFactoryFilter(io.servicetalk.client.api.ConnectionFactoryFilter) StreamingHttpConnectionFilter(io.servicetalk.http.api.StreamingHttpConnectionFilter) Arguments(org.junit.jupiter.params.provider.Arguments) OK(io.servicetalk.http.api.HttpResponseStatus.OK) InetSocketAddress(java.net.InetSocketAddress) Channel(io.netty.channel.Channel) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) List(java.util.List) Buffer(io.servicetalk.buffer.api.Buffer) CACHED(io.servicetalk.http.netty.AbstractNettyHttpServerTest.ExecutorSupplier.CACHED) ContextMap(io.servicetalk.context.api.ContextMap) RetryableException(io.servicetalk.transport.api.RetryableException) ReferenceCountUtil(io.netty.util.ReferenceCountUtil) TransportObserver(io.servicetalk.transport.api.TransportObserver) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) Http2MultiplexHandler(io.netty.handler.codec.http2.Http2MultiplexHandler) HTTP_2(io.servicetalk.http.netty.HttpProtocol.HTTP_2) Matchers.is(org.hamcrest.Matchers.is) Queue(java.util.Queue) HTTP_1(io.servicetalk.http.netty.HttpProtocol.HTTP_1) InetSocketAddress(java.net.InetSocketAddress) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) Channel(io.netty.channel.Channel) TransportObserver(io.servicetalk.transport.api.TransportObserver) ContextMap(io.servicetalk.context.api.ContextMap) NettyConnectionContext(io.servicetalk.transport.netty.internal.NettyConnectionContext) DelegatingConnectionFactory(io.servicetalk.client.api.DelegatingConnectionFactory) Http2MultiplexHandler(io.netty.handler.codec.http2.Http2MultiplexHandler) StreamingHttpConnectionFilter(io.servicetalk.http.api.StreamingHttpConnectionFilter) RetryableException(io.servicetalk.transport.api.RetryableException) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) DeliberateException(io.servicetalk.concurrent.internal.DeliberateException) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Nullable(javax.annotation.Nullable)

Example 10 with FilterableStreamingHttpConnection

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

the class AbstractLBHttpConnectionFactory method newConnection.

@Override
public final Single<LoadBalancedStreamingHttpConnection> newConnection(final ResolvedAddress resolvedAddress, @Nullable final TransportObserver observer) {
    return filterableConnectionFactory.newConnection(resolvedAddress, observer).map(conn -> {
        FilterableStreamingHttpConnection filteredConnection = connectionFilterFunction != null ? connectionFilterFunction.create(conn) : conn;
        ConnectionContext ctx = filteredConnection.connectionContext();
        Completable onClosing;
        if (ctx instanceof NettyConnectionContext) {
            // bondolo - I don't believe this is necessary, always the same as filteredConnection.onClose()
            // perhaps this is only needed for testing where the mock doesn't implement onClose()?
            onClosing = ((NettyConnectionContext) ctx).onClosing();
        } else {
            onClosing = filteredConnection.onClose();
        }
        final Publisher<? extends ConsumableEvent<Integer>> maxConcurrency = filteredConnection.transportEventStream(MAX_CONCURRENCY);
        final ReservableRequestConcurrencyController concurrencyController = newConcurrencyController(maxConcurrency, onClosing);
        return new LoadBalancedStreamingHttpConnection(protocolBinding.apply(filteredConnection), concurrencyController, connectStrategy instanceof HttpExecutionStrategy ? (HttpExecutionStrategy) connectStrategy : HttpExecutionStrategies.offloadNone());
    });
}
Also used : NettyConnectionContext(io.servicetalk.transport.netty.internal.NettyConnectionContext) Completable(io.servicetalk.concurrent.api.Completable) ReservableRequestConcurrencyController(io.servicetalk.client.api.internal.ReservableRequestConcurrencyController) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) NettyConnectionContext(io.servicetalk.transport.netty.internal.NettyConnectionContext) ConnectionContext(io.servicetalk.transport.api.ConnectionContext) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy)

Aggregations

FilterableStreamingHttpConnection (io.servicetalk.http.api.FilterableStreamingHttpConnection)10 HttpExecutionStrategy (io.servicetalk.http.api.HttpExecutionStrategy)5 Completable (io.servicetalk.concurrent.api.Completable)4 StreamingHttpClient (io.servicetalk.http.api.StreamingHttpClient)4 NettyConnectionContext (io.servicetalk.transport.netty.internal.NettyConnectionContext)4 InetSocketAddress (java.net.InetSocketAddress)4 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)4 MethodSource (org.junit.jupiter.params.provider.MethodSource)4 Single (io.servicetalk.concurrent.api.Single)3 ContextMap (io.servicetalk.context.api.ContextMap)3 FilterableStreamingHttpClient (io.servicetalk.http.api.FilterableStreamingHttpClient)3 StreamingHttpConnectionFilter (io.servicetalk.http.api.StreamingHttpConnectionFilter)3 StreamingHttpRequest (io.servicetalk.http.api.StreamingHttpRequest)3 ConnectionContext (io.servicetalk.transport.api.ConnectionContext)3 Channel (io.netty.channel.Channel)2 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)2 Http2MultiplexHandler (io.netty.handler.codec.http2.Http2MultiplexHandler)2 Buffer (io.servicetalk.buffer.api.Buffer)2 ReservableRequestConcurrencyController (io.servicetalk.client.api.internal.ReservableRequestConcurrencyController)2 DELIBERATE_EXCEPTION (io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION)2