Search in sources :

Example 1 with ByteStream

use of com.hotels.styx.api.ByteStream in project styx by ExpediaGroup.

the class StyxHostHttpClientTest method terminatesConnectionDueToUnsubscribedBody.

@Test
public void terminatesConnectionDueToUnsubscribedBody() {
    TestPublisher<Buffer> testPublisher = TestPublisher.create();
    Connection connection = mockConnection(just(LiveHttpResponse.response(OK).body(new ByteStream(testPublisher)).build()));
    ConnectionPool pool = mockPool(connection);
    Context context = mockContext();
    AtomicReference<LiveHttpResponse> receivedResponse = new AtomicReference<>();
    StyxHostHttpClient hostClient = new StyxHostHttpClient(pool);
    StepVerifier.create(hostClient.sendRequest(request, context)).consumeNextWith(receivedResponse::set).expectComplete().verify();
    StepVerifier.create(receivedResponse.get().body()).thenCancel().verify();
    verify(pool).closeConnection(any(Connection.class));
    verify(context).add(ORIGINID_CONTEXT_KEY, Id.id("mockorigin"));
}
Also used : Buffer(com.hotels.styx.api.Buffer) ConnectionPool(com.hotels.styx.client.connectionpool.ConnectionPool) HttpInterceptorContext(com.hotels.styx.server.HttpInterceptorContext) Support.requestContext(com.hotels.styx.support.Support.requestContext) Context(com.hotels.styx.api.HttpInterceptor.Context) ByteStream(com.hotels.styx.api.ByteStream) AtomicReference(java.util.concurrent.atomic.AtomicReference) LiveHttpResponse(com.hotels.styx.api.LiveHttpResponse) Test(org.junit.jupiter.api.Test)

Example 2 with ByteStream

use of com.hotels.styx.api.ByteStream in project styx by ExpediaGroup.

the class HttpResponseWriterTest method releasesContentChunksWhenFailsToConvertToNettyHeaders.

@Test
public void releasesContentChunksWhenFailsToConvertToNettyHeaders() throws Exception {
    CaptureHttpResponseWriteEventsHandler writeEventsCollector = new CaptureHttpResponseWriteEventsHandler();
    Buffer chunk1 = new Buffer("aaa", UTF_8);
    Buffer chunk2 = new Buffer("aaa", UTF_8);
    AtomicBoolean unsubscribed = new AtomicBoolean(false);
    EmbeddedChannel ch = new EmbeddedChannel(new CaptureChannelArgumentsHandler(channelArgs), writeEventsCollector, new SimpleChannelInboundHandler<LiveHttpResponse>() {

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, LiveHttpResponse response) throws Exception {
            HttpResponseWriter writer = new HttpResponseWriter(ctx, httpResponse -> {
                throw new RuntimeException();
            });
            CompletableFuture<Void> future = writer.write(response);
            contentObservable.onNext(chunk1);
            contentObservable.onNext(chunk2);
            contentObservable.onComplete();
            assertThat(future.isDone(), is(true));
            assertThat(toByteBuf(chunk1).refCnt(), is(0));
            assertThat(toByteBuf(chunk2).refCnt(), is(0));
            channelRead.set(true);
        }
    });
    LiveHttpResponse.Builder response = response(OK).cookies(responseCookie(",,,,", ",,,,").build());
    ch.writeInbound(response.body(new ByteStream(contentObservable.doOnCancel(() -> unsubscribed.set(true)))).build());
    assertThat(channelRead.get(), is(true));
}
Also used : Buffer(com.hotels.styx.api.Buffer) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) BeforeEach(org.junit.jupiter.api.BeforeEach) LiveHttpResponse.response(com.hotels.styx.api.LiveHttpResponse.response) LoggingHandler(io.netty.handler.logging.LoggingHandler) Buffers.toByteBuf(com.hotels.styx.api.Buffers.toByteBuf) LoggingTestSupport(com.hotels.styx.support.matchers.LoggingTestSupport) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Origin.newOriginBuilder(com.hotels.styx.api.extension.Origin.newOriginBuilder) CompletableFuture(java.util.concurrent.CompletableFuture) Disabled(org.junit.jupiter.api.Disabled) ArrayList(java.util.ArrayList) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) LoggingEventMatcher.loggingEvent(com.hotels.styx.support.matchers.LoggingEventMatcher.loggingEvent) ChannelPromise(io.netty.channel.ChannelPromise) EmitterProcessor(reactor.core.publisher.EmitterProcessor) Is.is(org.hamcrest.core.Is.is) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) InetAddress.getLoopbackAddress(java.net.InetAddress.getLoopbackAddress) ChannelOutboundHandlerAdapter(io.netty.channel.ChannelOutboundHandlerAdapter) UTF_8(java.nio.charset.StandardCharsets.UTF_8) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) TransportLostException(com.hotels.styx.api.exceptions.TransportLostException) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) EMPTY_LAST_CONTENT(io.netty.handler.codec.http.LastHttpContent.EMPTY_LAST_CONTENT) InetSocketAddress(java.net.InetSocketAddress) Buffer(com.hotels.styx.api.Buffer) Test(org.junit.jupiter.api.Test) ExecutionException(java.util.concurrent.ExecutionException) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) Level(ch.qos.logback.classic.Level) AfterEach(org.junit.jupiter.api.AfterEach) List(java.util.List) LiveHttpResponse(com.hotels.styx.api.LiveHttpResponse) ByteStream(com.hotels.styx.api.ByteStream) SimpleChannelInboundHandler(io.netty.channel.SimpleChannelInboundHandler) DefaultHttpResponse(io.netty.handler.codec.http.DefaultHttpResponse) OK(com.hotels.styx.api.HttpResponseStatus.OK) ResponseCookie.responseCookie(com.hotels.styx.api.ResponseCookie.responseCookie) Queue(java.util.Queue) ArrayDeque(java.util.ArrayDeque) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) LiveHttpResponse(com.hotels.styx.api.LiveHttpResponse) TransportLostException(com.hotels.styx.api.exceptions.TransportLostException) ExecutionException(java.util.concurrent.ExecutionException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) ByteStream(com.hotels.styx.api.ByteStream) Test(org.junit.jupiter.api.Test)

Example 3 with ByteStream

use of com.hotels.styx.api.ByteStream in project styx by ExpediaGroup.

the class HttpResponseWriterTest method ignoresLastEmptyHttpContentWriteOutcome.

@Test
public void ignoresLastEmptyHttpContentWriteOutcome() throws Exception {
    /*
         * It is necessary to ignore outcome of LastEmptyHttpContent.
         * This is because the full response would have been already sent,
         * and the remote end may have closed the connection before LastEmptyHttpContent
         * would have been written. This would result in an unnecessary
         * rejection of response writer future, even when the response in
         * fact was correctly sent. The following diagram illustrates the
         * scenario:
         *
         * 1. Styx HTTP Response writer writes the headers.
         *
         * 2. Styx HTTP Response writer writes the remaining content.
         *
         * 3. Remote receives the full response and closes the connection.
         *
         * 4. Styx HTTP Response Writer attempts to write the last empty HTTP
         *    content chunk. This will now fail because the TCP connection has
         *    closed.
         *
         * 5. HttpResponseWriter future completes unsuccessfully.
         *
         */
    EmbeddedChannel ch = new EmbeddedChannel(new CaptureChannelArgumentsHandler(channelArgs), new LoggingHandler(), new SimpleChannelInboundHandler<LiveHttpResponse>() {

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, LiveHttpResponse response) throws Exception {
            HttpResponseWriter writer = new HttpResponseWriter(ctx);
            CompletableFuture<Void> future = writer.write(response);
            // For response headers
            writeAck(channelArgs);
            assertThat(future.isDone(), is(false));
            contentObservable.onNext(new Buffer("aaa", UTF_8));
            // For content chunk
            writeAck(channelArgs);
            assertThat(future.isDone(), is(false));
            contentObservable.onComplete();
            // For EMPTY_LAST_CHUNK
            writeError(channelArgs);
            assertThat(future.isDone(), is(true));
            assertThat(future.isCompletedExceptionally(), is(false));
            channelRead.set(true);
        }
    });
    ch.writeInbound(response(OK).body(new ByteStream(contentObservable)).build());
    assertThat(channelRead.get(), is(true));
}
Also used : Buffer(com.hotels.styx.api.Buffer) LoggingHandler(io.netty.handler.logging.LoggingHandler) CompletableFuture(java.util.concurrent.CompletableFuture) ByteStream(com.hotels.styx.api.ByteStream) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) LiveHttpResponse(com.hotels.styx.api.LiveHttpResponse) TransportLostException(com.hotels.styx.api.exceptions.TransportLostException) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.jupiter.api.Test)

Example 4 with ByteStream

use of com.hotels.styx.api.ByteStream in project styx by ExpediaGroup.

the class HttpResponseWriterTest method sendsEmptyLastHttpContentWhenContentObservableCompletes.

@Test
public void sendsEmptyLastHttpContentWhenContentObservableCompletes() throws Exception {
    CaptureHttpResponseWriteEventsHandler writeEventsCollector = new CaptureHttpResponseWriteEventsHandler();
    EmbeddedChannel ch = new EmbeddedChannel(new CaptureChannelArgumentsHandler(channelArgs), writeEventsCollector, new SimpleChannelInboundHandler<LiveHttpResponse>() {

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, LiveHttpResponse response) throws Exception {
            HttpResponseWriter writer = new HttpResponseWriter(ctx);
            CompletableFuture<Void> future = writer.write(response);
            writeAck(channelArgs);
            assertThat(future.isDone(), is(false));
            contentObservable.onComplete();
            assertThat(future.isDone(), is(false));
            writeAck(channelArgs);
            assertThat(future.isDone(), is(true));
            channelRead.set(true);
        }
    });
    ch.writeInbound(response(OK).body(new ByteStream(contentObservable)).build());
    assertThat(channelRead.get(), is(true));
    List<Object> writeEvents = writeEventsCollector.writeEvents();
    assertThat(writeEvents.get(0), instanceOf(DefaultHttpResponse.class));
    assertThat(writeEvents.get(1), is(EMPTY_LAST_CONTENT));
}
Also used : EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) LiveHttpResponse(com.hotels.styx.api.LiveHttpResponse) TransportLostException(com.hotels.styx.api.exceptions.TransportLostException) ExecutionException(java.util.concurrent.ExecutionException) CompletableFuture(java.util.concurrent.CompletableFuture) DefaultHttpResponse(io.netty.handler.codec.http.DefaultHttpResponse) ByteStream(com.hotels.styx.api.ByteStream) Test(org.junit.jupiter.api.Test)

Example 5 with ByteStream

use of com.hotels.styx.api.ByteStream in project styx by ExpediaGroup.

the class HttpResponseWriterTest method completesFutureOnlyAfterContentObservableIsCompleted.

@Test
public void completesFutureOnlyAfterContentObservableIsCompleted() throws Exception {
    EmbeddedChannel ch = new EmbeddedChannel(new SimpleChannelInboundHandler<LiveHttpResponse>() {

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, LiveHttpResponse response) throws Exception {
            HttpResponseWriter writer = new HttpResponseWriter(ctx);
            CompletableFuture<Void> future = writer.write(response);
            assertThat(future.isDone(), is(false));
            contentObservable.onNext(new Buffer("aaa", UTF_8));
            assertThat(future.isDone(), is(false));
            contentObservable.onComplete();
            assertThat(future.isDone(), is(true));
            channelRead.set(true);
        }
    });
    ch.writeInbound(response(OK).body(new ByteStream(contentObservable)).build());
    assertThat(channelRead.get(), is(true));
}
Also used : Buffer(com.hotels.styx.api.Buffer) CompletableFuture(java.util.concurrent.CompletableFuture) ByteStream(com.hotels.styx.api.ByteStream) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) LiveHttpResponse(com.hotels.styx.api.LiveHttpResponse) TransportLostException(com.hotels.styx.api.exceptions.TransportLostException) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.jupiter.api.Test)

Aggregations

ByteStream (com.hotels.styx.api.ByteStream)12 LiveHttpResponse (com.hotels.styx.api.LiveHttpResponse)11 Test (org.junit.jupiter.api.Test)10 TransportLostException (com.hotels.styx.api.exceptions.TransportLostException)9 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)9 EmbeddedChannel (io.netty.channel.embedded.EmbeddedChannel)9 CompletableFuture (java.util.concurrent.CompletableFuture)9 ExecutionException (java.util.concurrent.ExecutionException)9 Buffer (com.hotels.styx.api.Buffer)8 LoggingHandler (io.netty.handler.logging.LoggingHandler)3 DefaultHttpResponse (io.netty.handler.codec.http.DefaultHttpResponse)2 InetSocketAddress (java.net.InetSocketAddress)2 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 Level (ch.qos.logback.classic.Level)1 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 Buffers.toByteBuf (com.hotels.styx.api.Buffers.toByteBuf)1 Context (com.hotels.styx.api.HttpInterceptor.Context)1 HttpResponseStatus (com.hotels.styx.api.HttpResponseStatus)1 OK (com.hotels.styx.api.HttpResponseStatus.OK)1 LiveHttpRequest (com.hotels.styx.api.LiveHttpRequest)1