Search in sources :

Example 6 with StreamingHttpClientFilter

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

the class DefaultMultiAddressUrlHttpClientBuilderTest method internalClientsUseDifferentExecutionContextWhenConfigured.

@Test
void internalClientsUseDifferentExecutionContextWhenConfigured() throws Exception {
    // Assert prerequisites first.
    // Use different strategies, as ExecutionContextExtension shares the same strategy.
    HttpExecutionStrategy internalExecutionStrategy = HttpExecutionStrategies.customStrategyBuilder().offloadNone().build();
    HttpExecutionStrategy externalExecutionStrategy = HttpExecutionStrategies.customStrategyBuilder().offloadAll().build();
    assertThat(internalExecutionStrategy, not(equalTo(externalExecutionStrategy)));
    BufferAllocator internalBufferAllocator = BufferAllocators.PREFER_DIRECT_ALLOCATOR;
    BufferAllocator externalBufferAllocator = BufferAllocators.PREFER_HEAP_ALLOCATOR;
    assertThat(internalBufferAllocator, not(equalTo(externalBufferAllocator)));
    assertThat(CTX.executor(), not(equalTo(INTERNAL_CLIENT_CTX.executor())));
    assertThat(CTX.ioExecutor(), not(equalTo(INTERNAL_CLIENT_CTX.ioExecutor())));
    try (ServerContext serverContext = HttpServers.forAddress(localAddress(0)).executionStrategy(offloadNever()).listenStreamingAndAwait((ctx, request, responseFactory) -> succeeded(responseFactory.ok()))) {
        AtomicReference<BufferAllocator> actualInternalBufferAllocator = new AtomicReference<>();
        AtomicReference<IoExecutor> actualInternalIoExecutor = new AtomicReference<>();
        AtomicReference<Executor> actualInternalExecutor = new AtomicReference<>();
        AtomicReference<ExecutionStrategy> actualInternalExecutionStrategy = new AtomicReference<>();
        final StreamingHttpClient streamingHttpClient = HttpClients.forMultiAddressUrl().initializer((scheme, address, builder) -> builder.executionStrategy(internalExecutionStrategy).executor(INTERNAL_CLIENT_CTX.executor()).ioExecutor(INTERNAL_CLIENT_CTX.ioExecutor()).bufferAllocator(internalBufferAllocator).executionStrategy(internalExecutionStrategy).appendClientFilter(client -> {
            HttpExecutionContext internalContext = client.executionContext();
            actualInternalBufferAllocator.set(internalContext.bufferAllocator());
            actualInternalExecutor.set(internalContext.executor());
            actualInternalIoExecutor.set(internalContext.ioExecutor());
            actualInternalExecutionStrategy.set(internalContext.executionStrategy());
            return new StreamingHttpClientFilter(client) {
            };
        })).executor(CTX.executor()).ioExecutor(CTX.ioExecutor()).executionStrategy(externalExecutionStrategy).bufferAllocator(externalBufferAllocator).buildStreaming();
        assertNotNull(streamingHttpClient);
        // Check external client
        final HttpExecutionContext executionContext = streamingHttpClient.executionContext();
        assertThat(executionContext.executor(), equalTo(CTX.executor()));
        assertThat(executionContext.executionStrategy(), equalTo(externalExecutionStrategy));
        assertThat(executionContext.ioExecutor(), equalTo(CTX.ioExecutor()));
        assertThat(executionContext.bufferAllocator(), equalTo(CTX.bufferAllocator()));
        // Make a request to trigger the filter execution that extracts the execution context.
        final HostAndPort address = HostAndPort.of((InetSocketAddress) serverContext.listenAddress());
        streamingHttpClient.reserveConnection(streamingHttpClient.get("http://" + address)).toFuture().get();
        // Check internal client
        assertThat(actualInternalBufferAllocator.get(), equalTo(internalBufferAllocator));
        assertThat(actualInternalExecutor.get(), equalTo(INTERNAL_CLIENT_CTX.executor()));
        assertThat(actualInternalIoExecutor.get(), equalTo(INTERNAL_CLIENT_CTX.ioExecutor()));
        assertThat(actualInternalExecutionStrategy.get(), equalTo(internalExecutionStrategy));
        streamingHttpClient.closeAsync().toFuture().get();
    }
}
Also used : Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) Matchers.not(org.hamcrest.Matchers.not) ExecutionContextExtension.cached(io.servicetalk.transport.netty.internal.ExecutionContextExtension.cached) StreamingHttpRequester(io.servicetalk.http.api.StreamingHttpRequester) ServiceDiscovererEvent(io.servicetalk.client.api.ServiceDiscovererEvent) AtomicReference(java.util.concurrent.atomic.AtomicReference) HttpRequester(io.servicetalk.http.api.HttpRequester) HttpExecutionStrategies.defaultStrategy(io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) ExecutionStrategy(io.servicetalk.transport.api.ExecutionStrategy) RegisterExtension(org.junit.jupiter.api.extension.RegisterExtension) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) HttpExecutionStrategies(io.servicetalk.http.api.HttpExecutionStrategies) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) Executor(io.servicetalk.concurrent.api.Executor) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext) AddressUtils.localAddress(io.servicetalk.transport.netty.internal.AddressUtils.localAddress) ExecutionContextExtension.immediate(io.servicetalk.transport.netty.internal.ExecutionContextExtension.immediate) ServerContext(io.servicetalk.transport.api.ServerContext) ServiceDiscoverer(io.servicetalk.client.api.ServiceDiscoverer) ExecutionContextExtension(io.servicetalk.transport.netty.internal.ExecutionContextExtension) BlockingHttpRequester(io.servicetalk.http.api.BlockingHttpRequester) BlockingStreamingHttpRequester(io.servicetalk.http.api.BlockingStreamingHttpRequester) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) InetSocketAddress(java.net.InetSocketAddress) Mockito.verify(org.mockito.Mockito.verify) BufferAllocators(io.servicetalk.buffer.netty.BufferAllocators) Test(org.junit.jupiter.api.Test) IoExecutor(io.servicetalk.transport.api.IoExecutor) Mockito.never(org.mockito.Mockito.never) BufferAllocator(io.servicetalk.buffer.api.BufferAllocator) Matchers.equalTo(org.hamcrest.Matchers.equalTo) HostAndPort(io.servicetalk.transport.api.HostAndPort) HttpExecutionStrategies.offloadNever(io.servicetalk.http.api.HttpExecutionStrategies.offloadNever) Mockito.mock(org.mockito.Mockito.mock) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) IoExecutor(io.servicetalk.transport.api.IoExecutor) AtomicReference(java.util.concurrent.atomic.AtomicReference) BufferAllocator(io.servicetalk.buffer.api.BufferAllocator) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) HostAndPort(io.servicetalk.transport.api.HostAndPort) Executor(io.servicetalk.concurrent.api.Executor) IoExecutor(io.servicetalk.transport.api.IoExecutor) ServerContext(io.servicetalk.transport.api.ServerContext) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) ExecutionStrategy(io.servicetalk.transport.api.ExecutionStrategy) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) Test(org.junit.jupiter.api.Test)

Example 7 with StreamingHttpClientFilter

use of io.servicetalk.http.api.StreamingHttpClientFilter 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 8 with StreamingHttpClientFilter

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

the class EnforceSequentialModeRequesterFilterTest method responseNeverCompletesIfRequestPayloadBodyNeverCompletes.

@Test
void responseNeverCompletesIfRequestPayloadBodyNeverCompletes() {
    StreamingHttpRequest request = REQ_RES_FACTORY.post("/").payloadBody(never());
    StreamingHttpClientFilter client = EnforceSequentialModeRequesterFilter.INSTANCE.create(this.client);
    AssertionError e = assertThrows(AssertionError.class, () -> StepVerifiers.create(client.request(request)).expectCancellable().expectSuccess().verify(Duration.ofMillis(100)));
    assertThat(e.getCause(), instanceOf(TimeoutException.class));
}
Also used : StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) TimeoutException(java.util.concurrent.TimeoutException) Test(org.junit.jupiter.api.Test)

Example 9 with StreamingHttpClientFilter

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

the class ServiceTalkContentEncodingTest method runTest.

@Override
protected void runTest(final HttpProtocol protocol, final Encoder clientEncoding, final Decoders clientDecoder, final Encoders serverEncoder, final Decoders serverDecoder, boolean valid) throws Throwable {
    try (ServerContext serverContext = HttpServers.forAddress(localAddress(0)).protocols(protocol.config).appendServiceFilter(service -> new StreamingHttpServiceFilter(service) {

        @Override
        public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
            return delegate().handle(ctx, request, responseFactory).map(resp -> {
                // content encoding should be stripped by the time the decoding is done.
                assertThat(resp.headers().get(ACCEPT_ENCODING), nullValue());
                CharSequence contentEncoding = resp.headers().get(CONTENT_ENCODING);
                boolean found = contentEncoding == null && (serverEncoder.list.isEmpty() || !request.headers().contains(ACCEPT_ENCODING));
                for (BufferEncoder be : serverEncoder.list) {
                    if (contentEncoding == null && contentEqualsIgnoreCase(be.encodingName(), identityEncoder().encodingName()) || contentEncoding != null && contentEqualsIgnoreCase(be.encodingName(), contentEncoding)) {
                        found = true;
                        break;
                    }
                }
                return found || !valid ? resp : responseFactory.ok().payloadBody(Publisher.from("server error: invalid " + CONTENT_ENCODING + ": " + contentEncoding), appSerializerUtf8FixLen());
            }).onErrorReturn(AssertionError.class, cause -> responseFactory.ok().payloadBody(Publisher.from("server error: " + cause.toString()), appSerializerUtf8FixLen()));
        }
    }).appendServiceFilter(new ContentEncodingHttpServiceFilter(serverEncoder.list, serverDecoder.group)).listenBlockingAndAwait((ctx, request, responseFactory) -> {
        String requestPayload = request.payloadBody(textSerializerUtf8());
        if (payloadAsString((byte) 'a').equals(requestPayload)) {
            return responseFactory.ok().payloadBody(payloadAsString((byte) 'b'), textSerializerUtf8());
        } else {
            return responseFactory.badRequest().payloadBody(requestPayload, textSerializerUtf8());
        }
    });
        BlockingHttpClient client = HttpClients.forSingleAddress(serverHostAndPort(serverContext)).protocols(protocol.config).appendClientFilter(new ContentEncodingHttpRequesterFilter(clientDecoder.group)).appendClientFilter(c -> new StreamingHttpClientFilter(c) {

            @Override
            protected Single<StreamingHttpResponse> request(final StreamingHttpRequester delegate, final StreamingHttpRequest request) {
                return Single.defer(() -> {
                    assertHeader(() -> clientEncoding.encoder == null ? null : clientEncoding.encoder.encodingName(), request.headers().get(CONTENT_ENCODING), true);
                    assertHeader(clientDecoder.group::advertisedMessageEncoding, request.headers().get(ACCEPT_ENCODING), false);
                    return delegate.request(request).shareContextOnSubscribe();
                });
            }
        }).buildBlocking()) {
        HttpResponse response = client.request(client.get("/").contentEncoding(clientEncoding.encoder).payloadBody(payloadAsString((byte) 'a'), textSerializerUtf8()));
        if (valid) {
            assertThat(response.status(), is(OK));
            // content encoding should be stripped by the time the decoding is done.
            assertThat(response.headers().get(CONTENT_ENCODING), nullValue());
            assertEquals(payloadAsString((byte) 'b'), response.payloadBody(textSerializerUtf8()));
        } else {
            assertThat(response.status(), is(UNSUPPORTED_MEDIA_TYPE));
        }
    }
}
Also used : StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Publisher(io.servicetalk.concurrent.api.Publisher) StreamingHttpRequester(io.servicetalk.http.api.StreamingHttpRequester) Supplier(java.util.function.Supplier) UNSUPPORTED_MEDIA_TYPE(io.servicetalk.http.api.HttpResponseStatus.UNSUPPORTED_MEDIA_TYPE) StreamingHttpServiceFilter(io.servicetalk.http.api.StreamingHttpServiceFilter) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) IsNull.nullValue(org.hamcrest.core.IsNull.nullValue) HttpSerializers.appSerializerUtf8FixLen(io.servicetalk.http.api.HttpSerializers.appSerializerUtf8FixLen) HttpSerializers.textSerializerUtf8(io.servicetalk.http.api.HttpSerializers.textSerializerUtf8) ContentEncodingHttpRequesterFilter(io.servicetalk.http.api.ContentEncodingHttpRequesterFilter) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) AddressUtils.serverHostAndPort(io.servicetalk.transport.netty.internal.AddressUtils.serverHostAndPort) BufferEncoder(io.servicetalk.encoding.api.BufferEncoder) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Nullable(javax.annotation.Nullable) BlockingHttpClient(io.servicetalk.http.api.BlockingHttpClient) AddressUtils.localAddress(io.servicetalk.transport.netty.internal.AddressUtils.localAddress) ServerContext(io.servicetalk.transport.api.ServerContext) Single(io.servicetalk.concurrent.api.Single) HttpResponse(io.servicetalk.http.api.HttpResponse) Identity.identityEncoder(io.servicetalk.encoding.api.Identity.identityEncoder) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) OK(io.servicetalk.http.api.HttpResponseStatus.OK) CharSequences.contentEqualsIgnoreCase(io.servicetalk.buffer.api.CharSequences.contentEqualsIgnoreCase) ACCEPT_ENCODING(io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING) ContentEncodingHttpServiceFilter(io.servicetalk.http.api.ContentEncodingHttpServiceFilter) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) Matchers.is(org.hamcrest.Matchers.is) CONTENT_ENCODING(io.servicetalk.http.api.HttpHeaderNames.CONTENT_ENCODING) StreamingHttpRequester(io.servicetalk.http.api.StreamingHttpRequester) BlockingHttpClient(io.servicetalk.http.api.BlockingHttpClient) ContentEncodingHttpRequesterFilter(io.servicetalk.http.api.ContentEncodingHttpRequesterFilter) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) ContentEncodingHttpServiceFilter(io.servicetalk.http.api.ContentEncodingHttpServiceFilter) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) HttpResponse(io.servicetalk.http.api.HttpResponse) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) StreamingHttpServiceFilter(io.servicetalk.http.api.StreamingHttpServiceFilter) ServerContext(io.servicetalk.transport.api.ServerContext) Single(io.servicetalk.concurrent.api.Single) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) BufferEncoder(io.servicetalk.encoding.api.BufferEncoder) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse)

Aggregations

StreamingHttpClientFilter (io.servicetalk.http.api.StreamingHttpClientFilter)9 StreamingHttpRequest (io.servicetalk.http.api.StreamingHttpRequest)7 StreamingHttpRequester (io.servicetalk.http.api.StreamingHttpRequester)7 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)7 Single (io.servicetalk.concurrent.api.Single)6 ServerContext (io.servicetalk.transport.api.ServerContext)6 AddressUtils.localAddress (io.servicetalk.transport.netty.internal.AddressUtils.localAddress)6 InetSocketAddress (java.net.InetSocketAddress)6 Single.succeeded (io.servicetalk.concurrent.api.Single.succeeded)5 OK (io.servicetalk.http.api.HttpResponseStatus.OK)5 StreamingHttpClient (io.servicetalk.http.api.StreamingHttpClient)5 StreamingHttpResponse (io.servicetalk.http.api.StreamingHttpResponse)5 HostAndPort (io.servicetalk.transport.api.HostAndPort)5 Nullable (javax.annotation.Nullable)5 Matchers.is (org.hamcrest.Matchers.is)5 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)5 Publisher (io.servicetalk.concurrent.api.Publisher)4 FilterableStreamingHttpConnection (io.servicetalk.http.api.FilterableStreamingHttpConnection)4 HttpResponse (io.servicetalk.http.api.HttpResponse)4 HttpResponseStatus (io.servicetalk.http.api.HttpResponseStatus)4