Search in sources :

Example 1 with StreamingHttpConnection

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

the class H2ResponseCancelTest method testConnection.

@Test
void testConnection() throws Exception {
    StreamingHttpConnection connection = streamingHttpConnection();
    AtomicBoolean connectionClosed = new AtomicBoolean();
    connection.onClose().whenFinally(() -> connectionClosed.set(true)).subscribe();
    requestCancellationResetsStreamButNotParentConnection(connection);
    assertThat("Connection closed unexpectedly", connectionClosed.get(), is(false));
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) StreamingHttpConnection(io.servicetalk.http.api.StreamingHttpConnection) ReservedStreamingHttpConnection(io.servicetalk.http.api.ReservedStreamingHttpConnection) Test(org.junit.jupiter.api.Test)

Example 2 with StreamingHttpConnection

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

the class ConnectionInfoTest method verifyToStringFormat.

@ParameterizedTest(name = "{index}: protocol={0}")
@EnumSource(HttpProtocol.class)
void verifyToStringFormat(HttpProtocol protocol) throws Exception {
    CtxInterceptingServiceFilterFactory ff = new CtxInterceptingServiceFilterFactory();
    nonOffloadingServiceFilterFactory(ff);
    serviceFilterFactory(ff);
    protocol(protocol.config);
    setUp(CACHED, CACHED_SERVER);
    StreamingHttpConnection connection = streamingHttpConnection();
    assertFormat(connection.connectionContext().toString(), protocol, true);
    StreamingHttpResponse response = makeRequest(connection.get(SVC_ECHO));
    assertResponse(response, protocol.version, OK, 0);
    assertFormat(ff.queue.take(), protocol, false);
    assertFormat(ff.queue.take(), protocol, false);
    assertThat(ff.queue, empty());
}
Also used : StreamingHttpConnection(io.servicetalk.http.api.StreamingHttpConnection) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) EnumSource(org.junit.jupiter.params.provider.EnumSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 3 with StreamingHttpConnection

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

the class HttpConnectionEmptyPayloadTest method headRequestContentEmpty.

@Test
void headRequestContentEmpty() throws Exception {
    try (CompositeCloseable closeable = AsyncCloseables.newCompositeCloseable()) {
        final int expectedContentLength = 128;
        byte[] expectedPayload = new byte[expectedContentLength];
        ThreadLocalRandom.current().nextBytes(expectedPayload);
        ServerContext serverContext = closeable.merge(HttpServers.forAddress(localAddress(0)).ioExecutor(executionContextRule.ioExecutor()).executionStrategy(offloadNever()).listenStreamingAndAwait((ctx, req, factory) -> {
            StreamingHttpResponse resp = factory.ok().payloadBody(from(HEAD.equals(req.method()) ? EMPTY_BUFFER : ctx.executionContext().bufferAllocator().newBuffer(expectedContentLength).writeBytes(expectedPayload)));
            resp.addHeader(CONTENT_LENGTH, String.valueOf(expectedContentLength));
            return succeeded(resp);
        }));
        StreamingHttpClient client = closeable.merge(forResolvedAddress(serverHostAndPort(serverContext)).ioExecutor(executionContextRule.ioExecutor()).protocols(h1().maxPipelinedRequests(3).build()).executor(executionContextRule.executor()).executionStrategy(defaultStrategy()).buildStreaming());
        StreamingHttpConnection connection = closeable.merge(client.reserveConnection(client.get("/")).toFuture().get());
        // Request HEAD, GET, HEAD to verify that we can keep reading data despite a HEAD request providing a hint
        // about content-length (and not actually providing the content).
        Single<StreamingHttpResponse> response1Single = connection.request(connection.newRequest(HEAD, "/"));
        Single<StreamingHttpResponse> response2Single = connection.request(connection.get("/"));
        Single<StreamingHttpResponse> response3Single = connection.request(connection.newRequest(HEAD, "/"));
        StreamingHttpResponse response = awaitIndefinitelyNonNull(response1Single);
        assertEquals(OK, response.status());
        CharSequence contentLength = response.headers().get(CONTENT_LENGTH);
        assertNotNull(contentLength);
        assertEquals(expectedContentLength, parseInt(contentLength.toString()));
        // Drain the current response content so we will be able to read the next response.
        response.messageBody().ignoreElements().toFuture().get();
        response = awaitIndefinitelyNonNull(response2Single);
        assertEquals(OK, response.status());
        contentLength = response.headers().get(CONTENT_LENGTH);
        assertNotNull(contentLength);
        assertEquals(expectedContentLength, parseInt(contentLength.toString()));
        Buffer buffer = awaitIndefinitelyNonNull(response.payloadBody().collect(() -> connection.connectionContext().executionContext().bufferAllocator().newBuffer(), Buffer::writeBytes));
        byte[] actualBytes = new byte[buffer.readableBytes()];
        buffer.readBytes(actualBytes);
        assertArrayEquals(expectedPayload, actualBytes);
        response = awaitIndefinitelyNonNull(response3Single);
        assertEquals(OK, response.status());
        contentLength = response.headers().get(CONTENT_LENGTH);
        assertNotNull(contentLength);
        assertEquals(expectedContentLength, parseInt(contentLength.toString()));
        response.messageBody().ignoreElements().toFuture().get();
    }
}
Also used : Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) EMPTY_BUFFER(io.servicetalk.buffer.api.EmptyBuffer.EMPTY_BUFFER) HttpExecutionStrategies.defaultStrategy(io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) RegisterExtension(org.junit.jupiter.api.extension.RegisterExtension) HEAD(io.servicetalk.http.api.HttpRequestMethod.HEAD) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) BlockingTestUtils.awaitIndefinitelyNonNull(io.servicetalk.concurrent.api.BlockingTestUtils.awaitIndefinitelyNonNull) AddressUtils.serverHostAndPort(io.servicetalk.transport.netty.internal.AddressUtils.serverHostAndPort) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Publisher.from(io.servicetalk.concurrent.api.Publisher.from) AddressUtils.localAddress(io.servicetalk.transport.netty.internal.AddressUtils.localAddress) ExecutionContextExtension.immediate(io.servicetalk.transport.netty.internal.ExecutionContextExtension.immediate) ServerContext(io.servicetalk.transport.api.ServerContext) HttpProtocolConfigs.h1(io.servicetalk.http.netty.HttpProtocolConfigs.h1) StreamingHttpConnection(io.servicetalk.http.api.StreamingHttpConnection) Single(io.servicetalk.concurrent.api.Single) CompositeCloseable(io.servicetalk.concurrent.api.CompositeCloseable) ExecutionContextExtension(io.servicetalk.transport.netty.internal.ExecutionContextExtension) CONTENT_LENGTH(io.servicetalk.http.api.HttpHeaderNames.CONTENT_LENGTH) OK(io.servicetalk.http.api.HttpResponseStatus.OK) Integer.parseInt(java.lang.Integer.parseInt) HttpClients.forResolvedAddress(io.servicetalk.http.netty.HttpClients.forResolvedAddress) Test(org.junit.jupiter.api.Test) Assertions.assertArrayEquals(org.junit.jupiter.api.Assertions.assertArrayEquals) Buffer(io.servicetalk.buffer.api.Buffer) AsyncCloseables(io.servicetalk.concurrent.api.AsyncCloseables) HttpExecutionStrategies.offloadNever(io.servicetalk.http.api.HttpExecutionStrategies.offloadNever) Buffer(io.servicetalk.buffer.api.Buffer) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) ServerContext(io.servicetalk.transport.api.ServerContext) CompositeCloseable(io.servicetalk.concurrent.api.CompositeCloseable) StreamingHttpConnection(io.servicetalk.http.api.StreamingHttpConnection) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Test(org.junit.jupiter.api.Test)

Example 4 with StreamingHttpConnection

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

the class HttpLifecycleObserverTest method testClientCancelsRequestAfterResponse.

@ParameterizedTest(name = "{displayName} [{index}] protocol={0}")
@EnumSource(HttpProtocol.class)
void testClientCancelsRequestAfterResponse(HttpProtocol protocol) throws Exception {
    TestPublisher<Buffer> serverResponsePayload = new TestPublisher<>();
    serviceFilterFactory(service -> new StreamingHttpServiceFilter(service) {

        @Override
        public Single<StreamingHttpResponse> handle(HttpServiceContext ctx, StreamingHttpRequest request, StreamingHttpResponseFactory responseFactory) {
            return request.payloadBody().ignoreElements().concat(succeeded(responseFactory.ok().payloadBody(serverResponsePayload)));
        }
    });
    setUp(protocol);
    StreamingHttpConnection connection = streamingHttpConnection();
    StreamingHttpRequest request = connection.post("/").payloadBody(Publisher.from(CONTENT.duplicate())).transform(// adds empty trailers
    new StatelessTrailersTransformer<>());
    StreamingHttpResponse response = connection.request(request).toFuture().get();
    assertResponse(response, protocol.version, OK);
    Future<Collection<Buffer>> payload = response.payloadBody().toFuture();
    payload.cancel(true);
    if (protocol == HttpProtocol.HTTP_1) {
        // wait for cancellation to close the connection:
        connection.onClose().toFuture().get();
    }
    // try to write server content to trigger write failure and close the server-side connection:
    serverResponsePayload.onNext(CONTENT.duplicate());
    bothTerminate.await();
    clientInOrder.verify(clientLifecycleObserver).onNewExchange();
    clientInOrder.verify(clientExchangeObserver).onConnectionSelected(any(ConnectionInfo.class));
    clientInOrder.verify(clientExchangeObserver).onRequest(any(StreamingHttpRequest.class));
    clientInOrder.verify(clientExchangeObserver).onResponse(any(StreamingHttpResponse.class));
    clientInOrder.verify(clientResponseObserver).onResponseCancel();
    clientRequestInOrder.verify(clientRequestObserver).onRequestData(any(Buffer.class));
    clientRequestInOrder.verify(clientRequestObserver).onRequestTrailers(any(HttpHeaders.class));
    clientRequestInOrder.verify(clientRequestObserver).onRequestComplete();
    clientInOrder.verify(clientExchangeObserver).onExchangeFinally();
    verifyNoMoreInteractions(clientLifecycleObserver, clientExchangeObserver, clientRequestObserver, clientResponseObserver);
    serverInOrder.verify(serverLifecycleObserver).onNewExchange();
    serverInOrder.verify(serverExchangeObserver).onConnectionSelected(any(ConnectionInfo.class));
    serverInOrder.verify(serverExchangeObserver).onRequest(any(StreamingHttpRequest.class));
    serverInOrder.verify(serverExchangeObserver).onResponse(any(StreamingHttpResponse.class));
    verify(serverResponseObserver, atMostOnce()).onResponseData(any(Buffer.class));
    serverInOrder.verify(serverResponseObserver).onResponseCancel();
    serverRequestInOrder.verify(serverRequestObserver).onRequestData(any(Buffer.class));
    serverRequestInOrder.verify(serverRequestObserver).onRequestComplete();
    serverInOrder.verify(serverExchangeObserver).onExchangeFinally();
    verifyNoMoreInteractions(serverLifecycleObserver, serverExchangeObserver, serverRequestObserver, serverResponseObserver);
}
Also used : Buffer(io.servicetalk.buffer.api.Buffer) HttpHeaders(io.servicetalk.http.api.HttpHeaders) TestPublisher(io.servicetalk.concurrent.api.TestPublisher) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) StreamingHttpServiceFilter(io.servicetalk.http.api.StreamingHttpServiceFilter) Single(io.servicetalk.concurrent.api.Single) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) Collection(java.util.Collection) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) ConnectionInfo(io.servicetalk.transport.api.ConnectionInfo) StreamingHttpConnection(io.servicetalk.http.api.StreamingHttpConnection) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) EnumSource(org.junit.jupiter.params.provider.EnumSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 5 with StreamingHttpConnection

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

the class FlushStrategyForClientApiTest method aggregatedApiShouldFlushOnEnd.

@Test
void aggregatedApiShouldFlushOnEnd() throws Exception {
    final StreamingHttpConnection connection = streamingHttpConnection();
    // The payload never completes, so since the aggregated API should use `flushOnEnd`, it should never flush.
    final Single<StreamingHttpResponse> responseSingle = connection.request(connection.asConnection().newRequest(POST, "/").addHeader(TRANSFER_ENCODING, CHUNKED).toStreamingRequest().payloadBody(Publisher.never()));
    try {
        responseSingle.toFuture().get(CI ? 900 : 100, MILLISECONDS);
        fail("Expected timeout");
    } catch (TimeoutException e) {
        // After the timeout, we've given the client some time to write and send the metadata, if it was going to.
        assertNull(request);
    }
}
Also used : StreamingHttpConnection(io.servicetalk.http.api.StreamingHttpConnection) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) TimeoutException(java.util.concurrent.TimeoutException) Test(org.junit.jupiter.api.Test)

Aggregations

StreamingHttpConnection (io.servicetalk.http.api.StreamingHttpConnection)29 StreamingHttpResponse (io.servicetalk.http.api.StreamingHttpResponse)16 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)14 StreamingHttpClient (io.servicetalk.http.api.StreamingHttpClient)13 Buffer (io.servicetalk.buffer.api.Buffer)12 Test (org.junit.jupiter.api.Test)12 SingleAddressHttpClientBuilder (io.servicetalk.http.api.SingleAddressHttpClientBuilder)10 HttpServerContext (io.servicetalk.http.api.HttpServerContext)9 RedirectConfigBuilder (io.servicetalk.http.api.RedirectConfigBuilder)9 MethodSource (org.junit.jupiter.params.provider.MethodSource)9 ExecutionException (java.util.concurrent.ExecutionException)6 BufferAllocator (io.servicetalk.buffer.api.BufferAllocator)5 EnumSource (org.junit.jupiter.params.provider.EnumSource)5 ServerContext (io.servicetalk.transport.api.ServerContext)4 Single (io.servicetalk.concurrent.api.Single)3 AddressUtils.serverHostAndPort (io.servicetalk.transport.netty.internal.AddressUtils.serverHostAndPort)3 CountDownLatch (java.util.concurrent.CountDownLatch)3 CharSequences.newAsciiString (io.servicetalk.buffer.api.CharSequences.newAsciiString)2 Publisher.fromInputStream (io.servicetalk.concurrent.api.Publisher.fromInputStream)2 Single.succeeded (io.servicetalk.concurrent.api.Single.succeeded)2