Search in sources :

Example 11 with Publisher

use of io.servicetalk.concurrent.api.Publisher in project servicetalk by apple.

the class ProtocolCompatibilityTest method serviceTalkServer.

private static TestServerContext serviceTalkServer(final ErrorMode errorMode, final boolean ssl, final GrpcExecutionStrategy strategy, @Nullable final String compression, @Nullable final Duration timeout, Queue<Throwable> reqStreamError) throws Exception {
    final Compat.CompatService compatService = new Compat.CompatService() {

        @Override
        public Publisher<CompatResponse> bidirectionalStreamingCall(final GrpcServiceContext ctx, final Publisher<CompatRequest> pub) {
            reqStreamError.add(SERVER_PROCESSED_TOKEN);
            maybeThrowFromRpc(errorMode);
            return pub.map(req -> response(req.getId())).beforeFinally(errorConsumer());
        }

        @Override
        public Single<CompatResponse> clientStreamingCall(final GrpcServiceContext ctx, final Publisher<CompatRequest> pub) {
            reqStreamError.add(SERVER_PROCESSED_TOKEN);
            maybeThrowFromRpc(errorMode);
            return pub.collect(() -> 0, (sum, req) -> sum + req.getId()).map(this::response).beforeFinally(errorConsumer());
        }

        @Override
        public Single<CompatResponse> scalarCall(final GrpcServiceContext ctx, final CompatRequest req) {
            maybeThrowFromRpc(errorMode);
            return succeeded(response(req.getId()));
        }

        @Override
        public Publisher<CompatResponse> serverStreamingCall(final GrpcServiceContext ctx, final CompatRequest req) {
            maybeThrowFromRpc(errorMode);
            return Publisher.fromIterable(() -> IntStream.range(0, req.getId()).iterator()).map(this::response);
        }

        private CompatResponse response(final int value) {
            if (errorMode == ErrorMode.SIMPLE_IN_RESPONSE) {
                throwGrpcStatusException();
            } else if (errorMode == ErrorMode.STATUS_IN_RESPONSE) {
                throwGrpcStatusExceptionWithStatus();
            }
            return computeResponse(value);
        }

        private TerminalSignalConsumer errorConsumer() {
            return new TerminalSignalConsumer() {

                @Override
                public void onComplete() {
                }

                @Override
                public void onError(final Throwable throwable) {
                    reqStreamError.add(throwable);
                }

                @Override
                public void cancel() {
                    reqStreamError.add(new IOException("cancelled"));
                }
            };
        }
    };
    final ServiceFactory serviceFactory = new ServiceFactory.Builder().bufferEncoders(serviceTalkCompressions(compression)).bufferDecoderGroup(serviceTalkDecompression(compression)).bidirectionalStreamingCall(strategy, compatService).clientStreamingCall(strategy, compatService).scalarCall(strategy, compatService).serverStreamingCall(strategy, compatService).build();
    final ServerContext serverContext = serviceTalkServerBuilder(errorMode, ssl, timeout, b -> b.executionStrategy(strategy)).listenAndAwait(serviceFactory);
    return TestServerContext.fromServiceTalkServerContext(serverContext);
}
Also used : Arrays(java.util.Arrays) CompatResponse(io.servicetalk.grpc.netty.CompatProto.ResponseContainer.CompatResponse) EmptyBufferDecoderGroup(io.servicetalk.encoding.api.EmptyBufferDecoderGroup) ServerSslConfigBuilder(io.servicetalk.transport.api.ServerSslConfigBuilder) GrpcClientMetadata(io.servicetalk.grpc.api.GrpcClientMetadata) TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) NettyServerBuilder(io.grpc.netty.NettyServerBuilder) SourceAdapters.fromSource(io.servicetalk.concurrent.api.SourceAdapters.fromSource) BidirectionalStreamingCallMetadata(io.servicetalk.grpc.netty.CompatProto.Compat.BidirectionalStreamingCallMetadata) Future(java.util.concurrent.Future) StatusProto(io.grpc.protobuf.StatusProto) Arrays.asList(java.util.Arrays.asList) Duration(java.time.Duration) DefaultTestCerts(io.servicetalk.test.resources.DefaultTestCerts) Status(io.grpc.Status) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) HttpProtocolConfigs.h2(io.servicetalk.http.netty.HttpProtocolConfigs.h2) DefaultTestCerts.loadServerKey(io.servicetalk.test.resources.DefaultTestCerts.loadServerKey) GrpcStatus(io.servicetalk.grpc.api.GrpcStatus) BlockingCompatClient(io.servicetalk.grpc.netty.CompatProto.Compat.BlockingCompatClient) BlockingQueue(java.util.concurrent.BlockingQueue) Processors.newSingleProcessor(io.servicetalk.concurrent.api.Processors.newSingleProcessor) Arguments(org.junit.jupiter.params.provider.Arguments) DefaultTestCerts.serverPemHostname(io.servicetalk.test.resources.DefaultTestCerts.serverPemHostname) BlockingIterable(io.servicetalk.concurrent.BlockingIterable) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) ArrayBlockingQueue(java.util.concurrent.ArrayBlockingQueue) ClientStreamingCallMetadata(io.servicetalk.grpc.netty.CompatProto.Compat.ClientStreamingCallMetadata) GRPC_TIMEOUT_HEADER_KEY(io.servicetalk.grpc.internal.DeadlineUtils.GRPC_TIMEOUT_HEADER_KEY) Compat(io.servicetalk.grpc.netty.CompatProto.Compat) StreamingHttpService(io.servicetalk.http.api.StreamingHttpService) Any(com.google.protobuf.Any) Matchers.is(org.hamcrest.Matchers.is) DefaultGrpcClientMetadata(io.servicetalk.grpc.api.DefaultGrpcClientMetadata) Codec(io.grpc.Codec) GrpcClientBuilder(io.servicetalk.grpc.api.GrpcClientBuilder) Assertions.fail(org.junit.jupiter.api.Assertions.fail) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) Compressor(io.grpc.Compressor) BlockingCompatService(io.servicetalk.grpc.netty.CompatProto.Compat.BlockingCompatService) ArrayList(java.util.ArrayList) InsecureTrustManagerFactory(io.netty.handler.ssl.util.InsecureTrustManagerFactory) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) CANCELLED(io.servicetalk.grpc.api.GrpcStatusCode.CANCELLED) Decompressor(io.grpc.Decompressor) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Server(io.grpc.Server) Nullable(javax.annotation.Nullable) SslContext(io.netty.handler.ssl.SslContext) Single(io.servicetalk.concurrent.api.Single) Completable(io.servicetalk.concurrent.api.Completable) IOException(java.io.IOException) StatusRuntimeException(io.grpc.StatusRuntimeException) ExecutionException(java.util.concurrent.ExecutionException) NettyBufferEncoders(io.servicetalk.encoding.netty.NettyBufferEncoders) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) GrpcExecutionStrategy(io.servicetalk.grpc.api.GrpcExecutionStrategy) DefaultTestCerts.loadServerPem(io.servicetalk.test.resources.DefaultTestCerts.loadServerPem) ArrayDeque(java.util.ArrayDeque) HttpServers(io.servicetalk.http.netty.HttpServers) GrpcSslContexts(io.grpc.netty.GrpcSslContexts) CompatRequest(io.servicetalk.grpc.netty.CompatProto.RequestContainer.CompatRequest) SocketAddress(java.net.SocketAddress) ManagedChannel(io.grpc.ManagedChannel) GrpcStatusCode(io.servicetalk.grpc.api.GrpcStatusCode) DEFAULT_TIMEOUT_SECONDS(io.servicetalk.concurrent.internal.TestTimeoutConstants.DEFAULT_TIMEOUT_SECONDS) GrpcStatusException(io.servicetalk.grpc.api.GrpcStatusException) GrpcExecutionStrategies.defaultStrategy(io.servicetalk.grpc.api.GrpcExecutionStrategies.defaultStrategy) StreamObserver(io.grpc.stub.StreamObserver) StreamingHttpClient(io.servicetalk.http.api.StreamingHttpClient) BufferDecoderGroup(io.servicetalk.encoding.api.BufferDecoderGroup) MethodSource(org.junit.jupiter.params.provider.MethodSource) ScalarCallMetadata(io.servicetalk.grpc.netty.CompatProto.Compat.ScalarCallMetadata) BufferDecoderGroupBuilder(io.servicetalk.encoding.api.BufferDecoderGroupBuilder) GrpcExecutionStrategies.offloadNever(io.servicetalk.grpc.api.GrpcExecutionStrategies.offloadNever) DEADLINE_EXCEEDED(io.servicetalk.grpc.api.GrpcStatusCode.DEADLINE_EXCEEDED) PublisherSource(io.servicetalk.concurrent.PublisherSource) Collection(java.util.Collection) GrpcPayloadWriter(io.servicetalk.grpc.api.GrpcPayloadWriter) InetSocketAddress(java.net.InetSocketAddress) GrpcServiceContext(io.servicetalk.grpc.api.GrpcServiceContext) Identity(io.servicetalk.encoding.api.Identity) CompatClient(io.servicetalk.grpc.netty.CompatProto.Compat.CompatClient) List(java.util.List) GrpcExecutionContext(io.servicetalk.grpc.api.GrpcExecutionContext) ClientSslConfigBuilder(io.servicetalk.transport.api.ClientSslConfigBuilder) CompressorRegistry(io.grpc.CompressorRegistry) Queue(java.util.Queue) Duration.ofMillis(java.time.Duration.ofMillis) IntStream(java.util.stream.IntStream) Publisher.never(io.servicetalk.concurrent.api.Publisher.never) CsvSource(org.junit.jupiter.params.provider.CsvSource) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Publisher(io.servicetalk.concurrent.api.Publisher) NANOSECONDS(java.util.concurrent.TimeUnit.NANOSECONDS) DeliberateException(io.servicetalk.concurrent.internal.DeliberateException) Processor(io.servicetalk.concurrent.SingleSource.Processor) StreamingHttpServiceFilter(io.servicetalk.http.api.StreamingHttpServiceFilter) OPENSSL(io.servicetalk.transport.api.SslProvider.OPENSSL) DecompressorRegistry(io.grpc.DecompressorRegistry) ServerStreamingCallMetadata(io.servicetalk.grpc.netty.CompatProto.Compat.ServerStreamingCallMetadata) GrpcServerBuilder(io.servicetalk.grpc.api.GrpcServerBuilder) BufferEncoder(io.servicetalk.encoding.api.BufferEncoder) HttpServerBuilder(io.servicetalk.http.api.HttpServerBuilder) AddressUtils.localAddress(io.servicetalk.transport.netty.internal.AddressUtils.localAddress) ServiceFactory(io.servicetalk.grpc.netty.CompatProto.Compat.ServiceFactory) ServerContext(io.servicetalk.transport.api.ServerContext) Processors.newPublisherProcessor(io.servicetalk.concurrent.api.Processors.newPublisherProcessor) SingleAddressHttpClientBuilder(io.servicetalk.http.api.SingleAddressHttpClientBuilder) NettyChannelBuilder(io.grpc.netty.NettyChannelBuilder) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) Any.pack(com.google.protobuf.Any.pack) Collections(java.util.Collections) HttpClients(io.servicetalk.http.netty.HttpClients) SECONDS(java.util.concurrent.TimeUnit.SECONDS) TerminalSignalConsumer(io.servicetalk.concurrent.api.TerminalSignalConsumer) ServiceFactory(io.servicetalk.grpc.netty.CompatProto.Compat.ServiceFactory) Compat(io.servicetalk.grpc.netty.CompatProto.Compat) Publisher(io.servicetalk.concurrent.api.Publisher) IOException(java.io.IOException) ServerContext(io.servicetalk.transport.api.ServerContext) BlockingCompatService(io.servicetalk.grpc.netty.CompatProto.Compat.BlockingCompatService) CompatResponse(io.servicetalk.grpc.netty.CompatProto.ResponseContainer.CompatResponse) GrpcServiceContext(io.servicetalk.grpc.api.GrpcServiceContext) CompatRequest(io.servicetalk.grpc.netty.CompatProto.RequestContainer.CompatRequest)

Example 12 with Publisher

use of io.servicetalk.concurrent.api.Publisher in project servicetalk by apple.

the class ProtoBufSerializationProviderBuilder method build0.

@SuppressWarnings("unchecked")
private void build0() {
    for (Map.Entry<Class<? extends MessageLite>, Parser<? extends MessageLite>> entry : types.entrySet()) {
        Class<MessageLite> messageType = (Class<MessageLite>) entry.getKey();
        Parser<MessageLite> parser = (Parser<MessageLite>) entry.getValue();
        Map<ContentCodec, HttpSerializer> serializersForType = new HashMap<>();
        Map<ContentCodec, HttpDeserializer> deserializersForType = new HashMap<>();
        for (ContentCodec codec : supportedCodings) {
            DefaultSerializer serializer = new DefaultSerializer(new ProtoBufSerializationProvider<>(messageType, codec, parser));
            HttpSerializer<MessageLite> httpSerializer = new ProtoHttpSerializer<>(serializer, codec, messageType);
            serializersForType.put(codec, httpSerializer);
            deserializersForType.put(codec, new HttpDeserializer<MessageLite>() {

                @Override
                public MessageLite deserialize(final HttpHeaders headers, final Buffer payload) {
                    return serializer.deserializeAggregatedSingle(payload, messageType);
                }

                @Override
                public BlockingIterable<MessageLite> deserialize(final HttpHeaders headers, final BlockingIterable<Buffer> payload) {
                    return serializer.deserialize(payload, messageType);
                }

                @Override
                public Publisher<MessageLite> deserialize(final HttpHeaders headers, final Publisher<Buffer> payload) {
                    return serializer.deserialize(payload, messageType);
                }
            });
        }
        serializers.put(messageType, serializersForType);
        deserializers.put(messageType, deserializersForType);
    }
}
Also used : HttpHeaders(io.servicetalk.http.api.HttpHeaders) HashMap(java.util.HashMap) DefaultSerializer(io.servicetalk.serialization.api.DefaultSerializer) HttpDeserializer(io.servicetalk.http.api.HttpDeserializer) BlockingIterable(io.servicetalk.concurrent.BlockingIterable) HttpSerializer(io.servicetalk.http.api.HttpSerializer) Buffer(io.servicetalk.buffer.api.Buffer) Publisher(io.servicetalk.concurrent.api.Publisher) MessageLite(com.google.protobuf.MessageLite) ContentCodec(io.servicetalk.encoding.api.ContentCodec) Parser(com.google.protobuf.Parser) HashMap(java.util.HashMap) Map(java.util.Map) Collections.unmodifiableMap(java.util.Collections.unmodifiableMap)

Example 13 with Publisher

use of io.servicetalk.concurrent.api.Publisher in project servicetalk by apple.

the class ProtocolCompatibilityTest method grpcJavaClient.

// Wrap grpc client in our client interface to simplify test code
private static CompatClient grpcJavaClient(final SocketAddress address, @Nullable final String compression, final boolean ssl, @Nullable Duration timeout) throws Exception {
    final NettyChannelBuilder builder = NettyChannelBuilder.forAddress(address);
    if (ssl) {
        final SslContext context = GrpcSslContexts.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
        builder.sslContext(context);
    } else {
        builder.usePlaintext();
    }
    final ManagedChannel channel = builder.build();
    // stub is immutable and each builder step returns a new instance.
    CompatGrpc.CompatStub stub = CompatGrpc.newStub(channel);
    if (compression != null) {
        stub = stub.withCompression(compression);
    }
    if (null != timeout) {
        stub = stub.withDeadlineAfter(timeout.toNanos(), NANOSECONDS);
    }
    final CompatGrpc.CompatStub finalStub = stub;
    return new CompatClient() {

        @Override
        public GrpcExecutionContext executionContext() {
            throw new UnsupportedOperationException();
        }

        @Override
        public Publisher<CompatResponse> bidirectionalStreamingCall(final Publisher<CompatRequest> request) {
            final PublisherSource.Processor<CompatResponse, CompatResponse> processor = newPublisherProcessor(3);
            sendRequest(request, finalStub.bidirectionalStreamingCall(adaptResponse(processor)));
            return fromSource(processor);
        }

        @Override
        public Publisher<CompatResponse> bidirectionalStreamingCall(final GrpcClientMetadata metadata, final Publisher<CompatRequest> request) {
            return bidirectionalStreamingCall(request);
        }

        @Deprecated
        @Override
        public Publisher<CompatResponse> bidirectionalStreamingCall(final BidirectionalStreamingCallMetadata metadata, final Publisher<CompatRequest> request) {
            return bidirectionalStreamingCall(request);
        }

        @SuppressWarnings("unchecked")
        @Override
        public Single<CompatResponse> clientStreamingCall(final Publisher<CompatRequest> request) {
            final Processor<CompatResponse, CompatResponse> processor = newSingleProcessor();
            final StreamObserver<CompatRequest> requestObserver = finalStub.clientStreamingCall(adaptResponse(processor));
            sendRequest(request, requestObserver);
            return (Single<CompatResponse>) processor;
        }

        @Deprecated
        @Override
        public Single<CompatResponse> clientStreamingCall(final ClientStreamingCallMetadata metadata, final Publisher<CompatRequest> request) {
            return clientStreamingCall(request);
        }

        @Override
        public Single<CompatResponse> clientStreamingCall(final GrpcClientMetadata metadata, final Publisher<CompatRequest> request) {
            return clientStreamingCall(request);
        }

        @SuppressWarnings("unchecked")
        @Override
        public Single<CompatResponse> scalarCall(final CompatRequest request) {
            final Processor<CompatResponse, CompatResponse> processor = newSingleProcessor();
            finalStub.scalarCall(request, adaptResponse(processor));
            return (Single<CompatResponse>) processor;
        }

        @Deprecated
        @Override
        public Single<CompatResponse> scalarCall(final ScalarCallMetadata metadata, final CompatRequest request) {
            return scalarCall(request);
        }

        @Override
        public Single<CompatResponse> scalarCall(final GrpcClientMetadata metadata, final CompatRequest request) {
            return scalarCall(request);
        }

        @Override
        public Publisher<CompatResponse> serverStreamingCall(final CompatRequest request) {
            final PublisherSource.Processor<CompatResponse, CompatResponse> processor = newPublisherProcessor(3);
            finalStub.serverStreamingCall(request, adaptResponse(processor));
            return fromSource(processor);
        }

        @Deprecated
        @Override
        public Publisher<CompatResponse> serverStreamingCall(final ServerStreamingCallMetadata metadata, final CompatRequest request) {
            return serverStreamingCall(request);
        }

        @Override
        public Publisher<CompatResponse> serverStreamingCall(final GrpcClientMetadata metadata, final CompatRequest request) {
            return serverStreamingCall(request);
        }

        @Override
        public void close() throws Exception {
            channel.shutdown().awaitTermination(DEFAULT_TIMEOUT_SECONDS, SECONDS);
        }

        @Override
        public Completable closeAsync() {
            throw new UnsupportedOperationException();
        }

        @Override
        public Completable onClose() {
            throw new UnsupportedOperationException();
        }

        @Override
        public BlockingCompatClient asBlockingClient() {
            throw new UnsupportedOperationException();
        }

        private void sendRequest(final Publisher<CompatRequest> request, final StreamObserver<CompatRequest> requestObserver) {
            request.whenOnComplete(requestObserver::onCompleted).whenOnError(requestObserver::onError).forEach(requestObserver::onNext);
        }

        private StreamObserver<CompatResponse> adaptResponse(final Processor<CompatResponse, CompatResponse> processor) {
            return new StreamObserver<CompatResponse>() {

                @Override
                public void onNext(final CompatResponse value) {
                    processor.onSuccess(value);
                }

                @Override
                public void onError(final Throwable t) {
                    processor.onError(t);
                }

                @Override
                public void onCompleted() {
                // ignored
                }
            };
        }

        private StreamObserver<CompatResponse> adaptResponse(final PublisherSource.Processor<CompatResponse, CompatResponse> processor) {
            return new StreamObserver<CompatResponse>() {

                @Override
                public void onNext(final CompatResponse value) {
                    processor.onNext(value);
                }

                @Override
                public void onError(final Throwable t) {
                    processor.onError(t);
                }

                @Override
                public void onCompleted() {
                    processor.onComplete();
                }
            };
        }
    };
}
Also used : StreamObserver(io.grpc.stub.StreamObserver) BidirectionalStreamingCallMetadata(io.servicetalk.grpc.netty.CompatProto.Compat.BidirectionalStreamingCallMetadata) Processors.newSingleProcessor(io.servicetalk.concurrent.api.Processors.newSingleProcessor) Processor(io.servicetalk.concurrent.SingleSource.Processor) Processors.newPublisherProcessor(io.servicetalk.concurrent.api.Processors.newPublisherProcessor) PublisherSource(io.servicetalk.concurrent.PublisherSource) ScalarCallMetadata(io.servicetalk.grpc.netty.CompatProto.Compat.ScalarCallMetadata) Publisher(io.servicetalk.concurrent.api.Publisher) GrpcClientMetadata(io.servicetalk.grpc.api.GrpcClientMetadata) DefaultGrpcClientMetadata(io.servicetalk.grpc.api.DefaultGrpcClientMetadata) ServerStreamingCallMetadata(io.servicetalk.grpc.netty.CompatProto.Compat.ServerStreamingCallMetadata) Single(io.servicetalk.concurrent.api.Single) BlockingCompatClient(io.servicetalk.grpc.netty.CompatProto.Compat.BlockingCompatClient) CompatClient(io.servicetalk.grpc.netty.CompatProto.Compat.CompatClient) CompatResponse(io.servicetalk.grpc.netty.CompatProto.ResponseContainer.CompatResponse) NettyChannelBuilder(io.grpc.netty.NettyChannelBuilder) ManagedChannel(io.grpc.ManagedChannel) CompatRequest(io.servicetalk.grpc.netty.CompatProto.RequestContainer.CompatRequest) ClientStreamingCallMetadata(io.servicetalk.grpc.netty.CompatProto.Compat.ClientStreamingCallMetadata) SslContext(io.netty.handler.ssl.SslContext)

Example 14 with Publisher

use of io.servicetalk.concurrent.api.Publisher 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 15 with Publisher

use of io.servicetalk.concurrent.api.Publisher in project servicetalk by apple.

the class AbstractStreamingHttpConnection method request.

@Override
public Single<StreamingHttpResponse> request(final StreamingHttpRequest request) {
    return defer(() -> {
        Publisher<Object> flatRequest;
        // See https://tools.ietf.org/html/rfc7230#section-3.3.3
        if (canAddRequestContentLength(request)) {
            flatRequest = setRequestContentLength(connectionContext().protocol(), request);
        } else {
            if (emptyMessageBody(request, request.messageBody())) {
                flatRequest = flatEmptyMessage(connectionContext().protocol(), request, request.messageBody());
            } else {
                // Defer subscribe to the messageBody until transport requests it to allow clients retry failed
                // requests with non-replayable messageBody
                flatRequest = Single.<Object>succeeded(request).concat(request.messageBody(), true);
                if (shouldAppendTrailers(connectionContext().protocol(), request)) {
                    flatRequest = flatRequest.scanWith(HeaderUtils::appendTrailersMapper);
                }
            }
            addRequestTransferEncodingIfNecessary(request);
        }
        final HttpExecutionStrategy strategy = requestExecutionStrategy(request, executionContext().executionStrategy());
        if (strategy.isSendOffloaded()) {
            flatRequest = flatRequest.subscribeOn(connectionContext.executionContext().executor(), IoThreadFactory.IoThread::currentThreadIsIoThread);
        }
        Single<StreamingHttpResponse> resp = invokeClient(flatRequest, determineFlushStrategyForApi(request));
        if (strategy.isMetadataReceiveOffloaded()) {
            resp = resp.publishOn(connectionContext.executionContext().executor(), IoThreadFactory.IoThread::currentThreadIsIoThread);
        }
        if (strategy.isDataReceiveOffloaded()) {
            resp = resp.map(response -> response.transformMessageBody(payload -> payload.publishOn(connectionContext.executionContext().executor(), IoThreadFactory.IoThread::currentThreadIsIoThread)));
        }
        return resp.shareContextOnSubscribe();
    });
}
Also used : FlushStrategy(io.servicetalk.transport.netty.internal.FlushStrategy) HeaderUtils.canAddRequestContentLength(io.servicetalk.http.netty.HeaderUtils.canAddRequestContentLength) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) HttpRequestMethod(io.servicetalk.http.api.HttpRequestMethod) Publisher(io.servicetalk.concurrent.api.Publisher) StreamingHttpResponses.newTransportResponse(io.servicetalk.http.api.StreamingHttpResponses.newTransportResponse) ConsumableEvent(io.servicetalk.client.api.ConsumableEvent) HttpResponseMetaData(io.servicetalk.http.api.HttpResponseMetaData) HttpApiConversions.isSafeToAggregate(io.servicetalk.http.api.HttpApiConversions.isSafeToAggregate) FilterableStreamingHttpConnection(io.servicetalk.http.api.FilterableStreamingHttpConnection) FlushStrategies.flushOnEnd(io.servicetalk.transport.netty.internal.FlushStrategies.flushOnEnd) HttpMetaData(io.servicetalk.http.api.HttpMetaData) IoThreadFactory(io.servicetalk.transport.api.IoThreadFactory) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) HttpApiConversions.isPayloadEmpty(io.servicetalk.http.api.HttpApiConversions.isPayloadEmpty) Objects.requireNonNull(java.util.Objects.requireNonNull) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) NettyConnectionContext(io.servicetalk.transport.netty.internal.NettyConnectionContext) HeaderUtils.addRequestTransferEncodingIfNecessary(io.servicetalk.http.netty.HeaderUtils.addRequestTransferEncodingIfNecessary) Publisher.from(io.servicetalk.concurrent.api.Publisher.from) ClientInvoker(io.servicetalk.http.api.ClientInvoker) HttpConnectionContext(io.servicetalk.http.api.HttpConnectionContext) Nullable(javax.annotation.Nullable) HttpExecutionContext(io.servicetalk.http.api.HttpExecutionContext) HeaderUtils.flatEmptyMessage(io.servicetalk.http.netty.HeaderUtils.flatEmptyMessage) Executors.immediate(io.servicetalk.concurrent.api.Executors.immediate) StreamingHttpRequestResponseFactory(io.servicetalk.http.api.StreamingHttpRequestResponseFactory) Single.defer(io.servicetalk.concurrent.api.Single.defer) HeaderUtils.setRequestContentLength(io.servicetalk.http.netty.HeaderUtils.setRequestContentLength) Single(io.servicetalk.concurrent.api.Single) HeaderUtils.emptyMessageBody(io.servicetalk.http.netty.HeaderUtils.emptyMessageBody) HeaderUtils.shouldAppendTrailers(io.servicetalk.http.netty.HeaderUtils.shouldAppendTrailers) Completable(io.servicetalk.concurrent.api.Completable) HTTP_EXECUTION_STRATEGY_KEY(io.servicetalk.http.api.HttpContextKeys.HTTP_EXECUTION_STRATEGY_KEY) HttpEventKey(io.servicetalk.http.api.HttpEventKey) HttpRequestMetaData(io.servicetalk.http.api.HttpRequestMetaData) IgnoreConsumedEvent(io.servicetalk.client.api.internal.IgnoreConsumedEvent) Publisher.failed(io.servicetalk.concurrent.api.Publisher.failed) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) REQ_EXPECT_CONTINUE(io.servicetalk.http.netty.HeaderUtils.REQ_EXPECT_CONTINUE) HttpHeadersFactory(io.servicetalk.http.api.HttpHeadersFactory) IoThreadFactory(io.servicetalk.transport.api.IoThreadFactory) HttpExecutionStrategy(io.servicetalk.http.api.HttpExecutionStrategy) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse)

Aggregations

Publisher (io.servicetalk.concurrent.api.Publisher)29 Buffer (io.servicetalk.buffer.api.Buffer)14 Single (io.servicetalk.concurrent.api.Single)14 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)13 Test (org.junit.jupiter.api.Test)13 Completable (io.servicetalk.concurrent.api.Completable)12 PublisherSource (io.servicetalk.concurrent.PublisherSource)11 Collection (java.util.Collection)11 SourceAdapters.toSource (io.servicetalk.concurrent.api.SourceAdapters.toSource)10 StreamingHttpResponse (io.servicetalk.http.api.StreamingHttpResponse)10 ArrayList (java.util.ArrayList)10 List (java.util.List)10 Matchers.instanceOf (org.hamcrest.Matchers.instanceOf)10 Matchers.is (org.hamcrest.Matchers.is)10 Subscription (io.servicetalk.concurrent.PublisherSource.Subscription)9 StreamingHttpRequest (io.servicetalk.http.api.StreamingHttpRequest)9 DEFAULT_ALLOCATOR (io.servicetalk.buffer.netty.BufferAllocators.DEFAULT_ALLOCATOR)8 Completable.completed (io.servicetalk.concurrent.api.Completable.completed)8 Executor (io.servicetalk.concurrent.api.Executor)8 HttpHeaders (io.servicetalk.http.api.HttpHeaders)8