Search in sources :

Example 21 with LiveHttpResponse

use of com.hotels.styx.api.LiveHttpResponse 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 22 with LiveHttpResponse

use of com.hotels.styx.api.LiveHttpResponse 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 23 with LiveHttpResponse

use of com.hotels.styx.api.LiveHttpResponse 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 24 with LiveHttpResponse

use of com.hotels.styx.api.LiveHttpResponse 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)

Example 25 with LiveHttpResponse

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

the class HttpResponseWriterTest method failsTheResultWhenResponseWriteFails.

@Test
public void failsTheResultWhenResponseWriteFails() throws Exception {
    EmbeddedChannel ch = new EmbeddedChannel(new CaptureChannelArgumentsHandler(channelArgs), 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));
            writeError(channelArgs);
            assertThat(future.isDone(), is(true));
            future.get(200, MILLISECONDS);
        }
    });
    assertThrows(ExecutionException.class, () -> ch.writeInbound(response(OK).body(new ByteStream(contentObservable)).build()));
}
Also used : 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

LiveHttpResponse (com.hotels.styx.api.LiveHttpResponse)80 Test (org.junit.jupiter.api.Test)69 LiveHttpRequest (com.hotels.styx.api.LiveHttpRequest)25 Support.requestContext (com.hotels.styx.support.Support.requestContext)21 Eventual (com.hotels.styx.api.Eventual)15 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)15 HttpHandler (com.hotels.styx.api.HttpHandler)14 EmbeddedChannel (io.netty.channel.embedded.EmbeddedChannel)14 Mono (reactor.core.publisher.Mono)14 ByteStream (com.hotels.styx.api.ByteStream)13 Context (com.hotels.styx.api.HttpInterceptor.Context)13 OK (com.hotels.styx.api.HttpResponseStatus.OK)13 LiveHttpResponse.response (com.hotels.styx.api.LiveHttpResponse.response)13 TransportLostException (com.hotels.styx.api.exceptions.TransportLostException)12 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)12 CompletableFuture (java.util.concurrent.CompletableFuture)12 Matchers.is (org.hamcrest.Matchers.is)12 Buffer (com.hotels.styx.api.Buffer)11 LiveHttpRequest.get (com.hotels.styx.api.LiveHttpRequest.get)11 HttpInterceptorContext (com.hotels.styx.server.HttpInterceptorContext)11