Search in sources :

Example 1 with TRANSFER_ENCODING

use of io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING in project servicetalk by apple.

the class H2PriorKnowledgeFeatureParityTest method clientSendsInvalidContentLength.

private void clientSendsInvalidContentLength(boolean addTrailers, BiConsumer<HttpHeaders, Integer> headersModifier) throws Exception {
    assumeFalse(!h2PriorKnowledge && addTrailers, "HTTP/1.1 does not support Content-Length with trailers");
    InetSocketAddress serverAddress = bindHttpEchoServer();
    try (BlockingHttpClient client = forSingleAddress(HostAndPort.of(serverAddress)).protocols(h2PriorKnowledge ? h2Default() : h1Default()).executionStrategy(clientExecutionStrategy).appendClientFilter(client1 -> new StreamingHttpClientFilter(client1) {

        @Override
        protected Single<StreamingHttpResponse> request(final StreamingHttpRequester delegate, final StreamingHttpRequest request) {
            return request.toRequest().map(req -> {
                req.headers().remove(TRANSFER_ENCODING);
                headersModifier.accept(req.headers(), req.payloadBody().readableBytes());
                return req.toStreamingRequest();
            }).flatMap(delegate::request);
        }
    }).buildBlocking()) {
        HttpRequest request = client.get("/").payloadBody("a", textSerializerUtf8());
        if (addTrailers) {
            request.trailers().set("mytrailer", "myvalue");
        }
        if (h2PriorKnowledge) {
            assertThrows(H2StreamResetException.class, () -> client.request(request));
        } else {
            try (ReservedBlockingHttpConnection reservedConn = client.reserveConnection(request)) {
                assertThrows(IOException.class, () -> {
                    // Either the current request or the next one should fail
                    reservedConn.request(request);
                    reservedConn.request(client.get("/"));
                });
            }
        }
    }
}
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) 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) HttpCookiePair(io.servicetalk.http.api.HttpCookiePair) 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) 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) 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) 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) 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) 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) 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) 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) 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) HttpRequest(io.servicetalk.http.api.HttpRequest) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) StreamingHttpRequester(io.servicetalk.http.api.StreamingHttpRequester) BlockingHttpClient(io.servicetalk.http.api.BlockingHttpClient) InetSocketAddress(java.net.InetSocketAddress) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) ReservedBlockingHttpConnection(io.servicetalk.http.api.ReservedBlockingHttpConnection)

Example 2 with TRANSFER_ENCODING

use of io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING in project servicetalk by apple.

the class H2PriorKnowledgeFeatureParityTest method bindHttpEchoServer.

private InetSocketAddress bindHttpEchoServer(@Nullable StreamingHttpServiceFilterFactory filterFactory, @Nullable CountDownLatch connectionOnClosingLatch) throws Exception {
    HttpServerBuilder serverBuilder = HttpServers.forAddress(localAddress(0)).protocols(h2PriorKnowledge ? h2Default() : h1Default());
    if (filterFactory != null) {
        serverBuilder.appendServiceFilter(filterFactory);
    }
    if (connectionOnClosingLatch != null) {
        serverBuilder.appendConnectionAcceptorFilter(original -> new DelegatingConnectionAcceptor(original) {

            @Override
            public Completable accept(final ConnectionContext context) {
                ((NettyConnectionContext) context).onClosing().whenFinally(connectionOnClosingLatch::countDown).subscribe();
                return completed();
            }
        });
    }
    h1ServerContext = serverBuilder.listenStreaming((ctx, request, responseFactory) -> {
        StreamingHttpResponse resp;
        if (request.headers().contains(EXPECT, CONTINUE)) {
            if (request.headers().contains(EXPECT_FAIL_HEADER)) {
                return succeeded(responseFactory.expectationFailed());
            } else {
                resp = responseFactory.continueResponse();
            }
        } else {
            resp = responseFactory.ok();
        }
        resp = resp.transformMessageBody(pub -> pub.ignoreElements().merge(request.messageBody())).transform(new StatelessTrailersTransformer<>());
        CharSequence contentType = request.headers().get(CONTENT_TYPE);
        if (contentType != null) {
            resp.setHeader(CONTENT_TYPE, contentType);
        }
        CharSequence contentLength = request.headers().get(CONTENT_LENGTH);
        if (contentLength != null) {
            resp.setHeader(CONTENT_LENGTH, contentLength);
        }
        CharSequence transferEncoding = request.headers().get(TRANSFER_ENCODING);
        if (transferEncoding != null) {
            resp.setHeader(TRANSFER_ENCODING, transferEncoding);
        }
        resp.headers().set(COOKIE, request.headers().valuesIterator(COOKIE));
        return succeeded(resp);
    }).toFuture().get();
    return (InetSocketAddress) h1ServerContext.listenAddress();
}
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) 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) HttpCookiePair(io.servicetalk.http.api.HttpCookiePair) 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) 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) 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) 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) 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) 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) 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) 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) 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) Completable(io.servicetalk.concurrent.api.Completable) InetSocketAddress(java.net.InetSocketAddress) HttpServerBuilder(io.servicetalk.http.api.HttpServerBuilder) DelegatingConnectionAcceptor(io.servicetalk.transport.api.DelegatingConnectionAcceptor) NettyConnectionContext(io.servicetalk.transport.netty.internal.NettyConnectionContext) ConnectionContext(io.servicetalk.transport.api.ConnectionContext) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse)

Example 3 with TRANSFER_ENCODING

use of io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING in project servicetalk by apple.

the class BlockingStreamingToStreamingService method handle.

@Override
public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
    return new Single<StreamingHttpResponse>() {

        @Override
        protected void handleSubscribe(final Subscriber<? super StreamingHttpResponse> subscriber) {
            final ThreadInterruptingCancellable tiCancellable = new ThreadInterruptingCancellable(currentThread());
            try {
                subscriber.onSubscribe(tiCancellable);
            } catch (Throwable cause) {
                handleExceptionFromOnSubscribe(subscriber, cause);
                return;
            }
            // This exists to help users with error propagation. If the user closes the payloadWriter and they throw
            // (e.g. try-with-resources) this processor is merged with the payloadWriter Publisher so the error will
            // still be propagated.
            final Processor exceptionProcessor = newCompletableProcessor();
            final BufferHttpPayloadWriter payloadWriter = new BufferHttpPayloadWriter(ctx.headersFactory().newTrailers());
            DefaultBlockingStreamingHttpServerResponse response = null;
            try {
                final Consumer<DefaultHttpResponseMetaData> sendMeta = (metaData) -> {
                    final DefaultStreamingHttpResponse result;
                    try {
                        // transfer-encoding takes precedence over content-length.
                        // > When a message does not have a Transfer-Encoding header field, a
                        // Content-Length header field can provide the anticipated size.
                        // https://tools.ietf.org/html/rfc7230#section-3.3.2
                        final HttpHeaders headers = metaData.headers();
                        final HttpProtocolVersion version = metaData.version();
                        boolean addTrailers = version.major() > 1 || isTransferEncodingChunked(headers);
                        if (!addTrailers && h1TrailersSupported(version) && !hasContentLength(headers) && // breaks our HttpResponseDecoder
                        !HEAD.equals(request.method())) {
                            // this is likely not supported in http/1.0 and it is possible that a response has
                            // neither header and the connection close indicates the end of the response.
                            // https://tools.ietf.org/html/rfc7230#section-3.3.3
                            headers.add(TRANSFER_ENCODING, CHUNKED);
                            addTrailers = true;
                        }
                        Publisher<Object> messageBody = fromSource(exceptionProcessor).merge(payloadWriter.connect());
                        if (addTrailers) {
                            messageBody = messageBody.concat(succeeded(payloadWriter.trailers()));
                        }
                        messageBody = messageBody.beforeSubscription(() -> new Subscription() {

                            @Override
                            public void request(final long n) {
                            }

                            @Override
                            public void cancel() {
                                tiCancellable.cancel();
                            }
                        });
                        result = new DefaultStreamingHttpResponse(metaData.status(), version, headers, metaData.context0(), ctx.executionContext().bufferAllocator(), messageBody, forTransportReceive(false, version, headers), ctx.headersFactory());
                    } catch (Throwable t) {
                        subscriber.onError(t);
                        throw t;
                    }
                    subscriber.onSuccess(result);
                };
                response = new DefaultBlockingStreamingHttpServerResponse(OK, request.version(), ctx.headersFactory().newHeaders(), payloadWriter, ctx.executionContext().bufferAllocator(), sendMeta);
                original.handle(ctx, request.toBlockingStreamingRequest(), response);
                // The user code has returned successfully, complete the processor so the response stream can
                // complete. If the user handles the request asynchronously (e.g. on another thread) they are
                // responsible for closing the payloadWriter.
                exceptionProcessor.onComplete();
            } catch (Throwable cause) {
                tiCancellable.setDone(cause);
                if (response == null || response.markMetaSent()) {
                    safeOnError(subscriber, cause);
                } else {
                    try {
                        exceptionProcessor.onError(cause);
                    } finally {
                        safeClose(payloadWriter, cause);
                    }
                }
                return;
            }
            tiCancellable.setDone();
        }
    };
}
Also used : HttpProtocolVersion.h1TrailersSupported(io.servicetalk.http.api.HttpProtocolVersion.h1TrailersSupported) DefaultPayloadInfo.forTransportReceive(io.servicetalk.http.api.DefaultPayloadInfo.forTransportReceive) Publisher(io.servicetalk.concurrent.api.Publisher) Subscriber(io.servicetalk.concurrent.SingleSource.Subscriber) ConnectablePayloadWriter(io.servicetalk.concurrent.api.internal.ConnectablePayloadWriter) PayloadWriterUtils.safeClose(io.servicetalk.oio.api.internal.PayloadWriterUtils.safeClose) Thread.currentThread(java.lang.Thread.currentThread) ThreadInterruptingCancellable(io.servicetalk.concurrent.internal.ThreadInterruptingCancellable) SourceAdapters.fromSource(io.servicetalk.concurrent.api.SourceAdapters.fromSource) HeaderUtils.isTransferEncodingChunked(io.servicetalk.http.api.HeaderUtils.isTransferEncodingChunked) HttpExecutionStrategies.defaultStrategy(io.servicetalk.http.api.HttpExecutionStrategies.defaultStrategy) HEAD(io.servicetalk.http.api.HttpRequestMethod.HEAD) Objects.requireNonNull(java.util.Objects.requireNonNull) SubscriberUtils.safeOnError(io.servicetalk.concurrent.internal.SubscriberUtils.safeOnError) Processors.newCompletableProcessor(io.servicetalk.concurrent.api.Processors.newCompletableProcessor) CHUNKED(io.servicetalk.http.api.HttpHeaderValues.CHUNKED) SubscriberUtils.handleExceptionFromOnSubscribe(io.servicetalk.concurrent.internal.SubscriberUtils.handleExceptionFromOnSubscribe) Single(io.servicetalk.concurrent.api.Single) Completable(io.servicetalk.concurrent.api.Completable) OFFLOAD_RECEIVE_META_STRATEGY(io.servicetalk.http.api.DefaultHttpExecutionStrategy.OFFLOAD_RECEIVE_META_STRATEGY) TRANSFER_ENCODING(io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING) IOException(java.io.IOException) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription) OK(io.servicetalk.http.api.HttpResponseStatus.OK) Consumer(java.util.function.Consumer) BlockingUtils.blockingToCompletable(io.servicetalk.http.api.BlockingUtils.blockingToCompletable) HeaderUtils.hasContentLength(io.servicetalk.http.api.HeaderUtils.hasContentLength) Buffer(io.servicetalk.buffer.api.Buffer) Processor(io.servicetalk.concurrent.CompletableSource.Processor) Processors.newCompletableProcessor(io.servicetalk.concurrent.api.Processors.newCompletableProcessor) Processor(io.servicetalk.concurrent.CompletableSource.Processor) ThreadInterruptingCancellable(io.servicetalk.concurrent.internal.ThreadInterruptingCancellable) Publisher(io.servicetalk.concurrent.api.Publisher) Single(io.servicetalk.concurrent.api.Single) Subscriber(io.servicetalk.concurrent.SingleSource.Subscriber) Subscription(io.servicetalk.concurrent.PublisherSource.Subscription)

Example 4 with TRANSFER_ENCODING

use of io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING in project servicetalk by apple.

the class TestServiceStreaming method newEchoResponse.

private static StreamingHttpResponse newEchoResponse(final StreamingHttpRequest req, final StreamingHttpResponseFactory factory) {
    final StreamingHttpResponse response = factory.ok().version(req.version()).transformMessageBody(pub -> pub.ignoreElements().merge(req.messageBody())).transform(new StatelessTrailersTransformer<>());
    final CharSequence contentLength = req.headers().get(CONTENT_LENGTH);
    if (contentLength != null) {
        response.addHeader(CONTENT_LENGTH, contentLength);
    }
    final CharSequence contentType = req.headers().get(CONTENT_TYPE);
    if (contentType != null) {
        response.addHeader(CONTENT_TYPE, contentType);
    }
    final CharSequence transferEncoding = req.headers().get(TRANSFER_ENCODING);
    if (transferEncoding != null) {
        response.addHeader(TRANSFER_ENCODING, transferEncoding);
    }
    return response;
}
Also used : StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Publisher(io.servicetalk.concurrent.api.Publisher) LoggerFactory(org.slf4j.LoggerFactory) CONTENT_TYPE(io.servicetalk.http.api.HttpHeaderNames.CONTENT_TYPE) Publisher.empty(io.servicetalk.concurrent.api.Publisher.empty) Function(java.util.function.Function) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) Publisher.from(io.servicetalk.concurrent.api.Publisher.from) DELIBERATE_EXCEPTION(io.servicetalk.concurrent.internal.DeliberateException.DELIBERATE_EXCEPTION) ConnectionContext(io.servicetalk.transport.api.ConnectionContext) Logger(org.slf4j.Logger) Single(io.servicetalk.concurrent.api.Single) Completable(io.servicetalk.concurrent.api.Completable) NO_CONTENT(io.servicetalk.http.api.HttpResponseStatus.NO_CONTENT) TRANSFER_ENCODING(io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING) StatelessTrailersTransformer(io.servicetalk.http.api.StatelessTrailersTransformer) CONTENT_LENGTH(io.servicetalk.http.api.HttpHeaderNames.CONTENT_LENGTH) Single.never(io.servicetalk.concurrent.api.Single.never) Buffer(io.servicetalk.buffer.api.Buffer) String.valueOf(java.lang.String.valueOf) StreamingHttpService(io.servicetalk.http.api.StreamingHttpService) NOT_FOUND(io.servicetalk.http.api.HttpResponseStatus.NOT_FOUND) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse)

Example 5 with TRANSFER_ENCODING

use of io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING in project servicetalk by apple.

the class DefaultContainerResponseWriter method sendResponse.

private void sendResponse(final long contentLength, @Nullable final Publisher<Buffer> content, final ContainerResponse containerResponse) {
    final HttpResponseStatus status = getStatus(containerResponse);
    final StreamingHttpResponse response;
    if (content != null && !isHeadRequest()) {
        final HttpExecutionStrategy executionStrategy = getResponseExecutionStrategy(request);
        // TODO(scott): use request factory methods that accept a payload body to avoid overhead of payloadBody.
        final Publisher<Buffer> payloadBody = (executionStrategy != null && executionStrategy.isSendOffloaded() ? content.subscribeOn(serviceCtx.executionContext().executor(), IoThreadFactory.IoThread::currentThreadIsIoThread) : content).beforeCancel(// Cleanup internal state if server cancels response body
        this::cancelResponse);
        response = responseFactory.newResponse(status).version(protocolVersion).payloadBody(payloadBody);
    } else {
        response = responseFactory.newResponse(status).version(protocolVersion);
    }
    final HttpHeaders headers = response.headers();
    // If we use HTTP/2 protocol all headers MUST be in lower case
    final boolean isH2 = response.version().major() == 2;
    containerResponse.getHeaders().forEach((k, vs) -> vs.forEach(v -> {
        headers.add(isH2 ? k.toLowerCase() : k, v == null ? emptyAsciiString() : asCharSequence(v));
    }));
    if (!headers.contains(CONTENT_LENGTH)) {
        if (contentLength == UNKNOWN_RESPONSE_LENGTH) {
            // We can omit Transfer-Encoding for HEAD per https://tools.ietf.org/html/rfc7231#section-4.3.2
            if (!isHeadRequest() && !HTTP_1_0.equals(protocolVersion)) {
                headers.set(TRANSFER_ENCODING, CHUNKED);
            }
        } else {
            headers.set(CONTENT_LENGTH, contentLength == 0 ? ZERO : Long.toString(contentLength));
            headers.removeIgnoreCase(TRANSFER_ENCODING, CHUNKED);
        }
    }
    responseSubscriber.onSuccess(response);
}
Also used : Buffer(io.servicetalk.buffer.api.Buffer) AtomicIntegerFieldUpdater(java.util.concurrent.atomic.AtomicIntegerFieldUpdater) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Publisher(io.servicetalk.concurrent.api.Publisher) Subscriber(io.servicetalk.concurrent.SingleSource.Subscriber) LoggerFactory(org.slf4j.LoggerFactory) HttpHeaders(io.servicetalk.http.api.HttpHeaders) Cancellable(io.servicetalk.concurrent.Cancellable) RequestProperties.getResponseExecutionStrategy(io.servicetalk.http.router.jersey.internal.RequestProperties.getResponseExecutionStrategy) ConnectableBufferOutputStream(io.servicetalk.concurrent.api.internal.ConnectableBufferOutputStream) RequestProperties.getResponseBufferPublisher(io.servicetalk.http.router.jersey.internal.RequestProperties.getResponseBufferPublisher) ContainerException(org.glassfish.jersey.server.ContainerException) ZERO(io.servicetalk.http.api.HttpHeaderValues.ZERO) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) IoThreadFactory(io.servicetalk.transport.api.IoThreadFactory) RequestProperties.getRequestCancellable(io.servicetalk.http.router.jersey.internal.RequestProperties.getRequestCancellable) Collectors.toMap(java.util.stream.Collectors.toMap) Map(java.util.Map) Objects.requireNonNull(java.util.Objects.requireNonNull) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) HttpProtocolVersion(io.servicetalk.http.api.HttpProtocolVersion) CharSequences.emptyAsciiString(io.servicetalk.buffer.api.CharSequences.emptyAsciiString) AtomicIntegerFieldUpdater.newUpdater(java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater) Status(javax.ws.rs.core.Response.Status) ContainerResponseWriter(org.glassfish.jersey.server.spi.ContainerResponseWriter) Nullable(javax.annotation.Nullable) CHUNKED(io.servicetalk.http.api.HttpHeaderValues.CHUNKED) OutputStream(java.io.OutputStream) Logger(org.slf4j.Logger) TRANSFER_ENCODING(io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING) IOException(java.io.IOException) ContainerRequest(org.glassfish.jersey.server.ContainerRequest) CONTENT_LENGTH(io.servicetalk.http.api.HttpHeaderNames.CONTENT_LENGTH) TimeUnit(java.util.concurrent.TimeUnit) StatusType(javax.ws.rs.core.Response.StatusType) ContainerResponse(org.glassfish.jersey.server.ContainerResponse) HEAD(javax.ws.rs.HttpMethod.HEAD) Buffer(io.servicetalk.buffer.api.Buffer) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) Function.identity(java.util.function.Function.identity) Collections.unmodifiableMap(java.util.Collections.unmodifiableMap) Arrays.stream(java.util.Arrays.stream) HttpResponseStatus(io.servicetalk.http.api.HttpResponseStatus) System.arraycopy(java.lang.System.arraycopy) HTTP_1_0(io.servicetalk.http.api.HttpProtocolVersion.HTTP_1_0) HttpHeaders(io.servicetalk.http.api.HttpHeaders) HttpResponseStatus(io.servicetalk.http.api.HttpResponseStatus) IoThreadFactory(io.servicetalk.transport.api.IoThreadFactory) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse)

Aggregations

Buffer (io.servicetalk.buffer.api.Buffer)7 TRANSFER_ENCODING (io.servicetalk.http.api.HttpHeaderNames.TRANSFER_ENCODING)7 Single (io.servicetalk.concurrent.api.Single)6 CONTENT_LENGTH (io.servicetalk.http.api.HttpHeaderNames.CONTENT_LENGTH)6 HttpServiceContext (io.servicetalk.http.api.HttpServiceContext)6 StreamingHttpResponse (io.servicetalk.http.api.StreamingHttpResponse)6 StreamingHttpResponseFactory (io.servicetalk.http.api.StreamingHttpResponseFactory)6 Publisher (io.servicetalk.concurrent.api.Publisher)5 HttpHeaders (io.servicetalk.http.api.HttpHeaders)5 OK (io.servicetalk.http.api.HttpResponseStatus.OK)5 StatelessTrailersTransformer (io.servicetalk.http.api.StatelessTrailersTransformer)5 StreamingHttpRequest (io.servicetalk.http.api.StreamingHttpRequest)5 String.valueOf (java.lang.String.valueOf)5 Nullable (javax.annotation.Nullable)5 Completable (io.servicetalk.concurrent.api.Completable)4 IOException (java.io.IOException)4 ServerBootstrap (io.netty.bootstrap.ServerBootstrap)3 Channel (io.netty.channel.Channel)3 ChannelDuplexHandler (io.netty.channel.ChannelDuplexHandler)3 ChannelHandler (io.netty.channel.ChannelHandler)3