@VisibleForTesting
    static void deframeAndRespond(ServiceRequestContext ctx,
                                  AggregatedHttpResponse grpcResponse,
                                  CompletableFuture<HttpResponse> res,
                                  UnframedGrpcErrorHandler unframedGrpcErrorHandler,
                                  @Nullable
                                  Function<AggregatedHttpResponse, AggregatedHttpResponse> responseConverter) {
        final HttpHeaders trailers = !grpcResponse.trailers().isEmpty() ?
                                     grpcResponse.trailers() : grpcResponse.headers();
        final String grpcStatusCode = trailers.get(GrpcHeaderNames.GRPC_STATUS);
        if (grpcStatusCode == null) {
            PooledObjects.close(grpcResponse.content());
            res.completeExceptionally(new NullPointerException("grpcStatusCode must not be null"));
            logger.warn("{} A gRPC response must have the {} header. response: {}",
                        ctx, GrpcHeaderNames.GRPC_STATUS, grpcResponse);
            return;
        }
        Status grpcStatus = Status.fromCodeValue(Integer.parseInt(grpcStatusCode));
        final String grpcMessage = trailers.get(GrpcHeaderNames.GRPC_MESSAGE);
        if (!Strings.isNullOrEmpty(grpcMessage)) {
            grpcStatus = grpcStatus.withDescription(grpcMessage);
        }

        if (grpcStatus.getCode() != Code.OK) {
            PooledObjects.close(grpcResponse.content());
            try {
                res.complete(unframedGrpcErrorHandler.handle(ctx, grpcStatus, grpcResponse));
            } catch (Exception e) {
                res.completeExceptionally(e);
            }
            return;
        }

        final MediaType grpcMediaType = grpcResponse.contentType();
        if (grpcMediaType == null) {
            PooledObjects.close(grpcResponse.content());
            res.completeExceptionally(new NullPointerException("MediaType is undefined"));
            return;
        }

        final ResponseHeadersBuilder unframedHeaders = grpcResponse.headers().toBuilder();
        unframedHeaders.set(GrpcHeaderNames.GRPC_STATUS, grpcStatusCode); // grpcStatusCode is 0 which is OK.

        final ArmeriaMessageDeframer deframer = new ArmeriaMessageDeframer(
                // Max outbound message size is handled by the GrpcService, so we don't need to set it here.
                Integer.MAX_VALUE);
        final Subscriber<DeframedMessage> subscriber = singleSubscriber(
                unframedHeaders, res, responseConverter);
        grpcResponse.toHttpResponse().decode(deframer, ctx.alloc())
                    .subscribe(subscriber, ctx.eventLoop(), SubscriptionOption.WITH_POOLED_OBJECTS);
    }
Creates a new instance that decorates the specified {@link HttpService}.
grpc/src/main/java/com/linecorp/armeria/server/grpc/AbstractUnframedGrpcService.java