@Override
    public HttpResponse handle(ServiceRequestContext ctx, Status status, AggregatedHttpResponse response) {
        final ByteBuf buffer = ctx.alloc().buffer();
        final Code grpcCode = status.getCode();
        final String grpcMessage = status.getDescription();
        final Throwable cause = responseCause(ctx);
        final HttpStatus httpStatus = statusMappingFunction.apply(ctx, status, cause);
        assert httpStatus != null : "Default statusMappingFunction returned null?";
        final HttpHeaders trailers = !response.trailers().isEmpty() ?
                                     response.trailers() : response.headers();
        final String grpcStatusDetailsBin = trailers.get(GrpcHeaderNames.GRPC_STATUS_DETAILS_BIN);
        final ResponseHeaders responseHeaders = ResponseHeaders.builder(httpStatus)
                                                               .contentType(MediaType.JSON_UTF_8)
                                                               .addInt(GrpcHeaderNames.GRPC_STATUS,
                                                                       grpcCode.value())
                                                               .build();
        boolean success = false;
        try (OutputStream outputStream = new ByteBufOutputStream(buffer);
             JsonGenerator jsonGenerator = mapper.createGenerator(outputStream)) {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeNumberField("code", grpcCode.value());
            jsonGenerator.writeStringField("grpc-code", grpcCode.name());
            if (grpcMessage != null) {
                jsonGenerator.writeStringField("message", grpcMessage);
            }
            if (cause != null && ctx.config().verboseResponses()) {
                jsonGenerator.writeStringField("stack-trace", Exceptions.traceText(cause));
            }
            if (!Strings.isNullOrEmpty(grpcStatusDetailsBin)) {
                com.google.rpc.Status rpcStatus = null;
                try {
                    rpcStatus = decodeGrpcStatusDetailsBin(grpcStatusDetailsBin);
                } catch (InvalidProtocolBufferException e) {
                    logger.warn("Unexpected exception while decoding grpc-status-details-bin: {}",
                                grpcStatusDetailsBin, e);
                }
                if (rpcStatus != null) {
                    jsonGenerator.writeFieldName("details");
                    writeErrorDetails(ctx, rpcStatus.getDetailsList(), jsonGenerator);
                }
            }
            jsonGenerator.writeEndObject();
            jsonGenerator.flush();
            success = true;
        } catch (IOException e) {
            logger.warn("{} Unexpected exception while generating a JSON response", ctx, e);
        } finally {
            if (!success) {
                buffer.release();
            }
        }
        if (success) {
            return HttpResponse.of(responseHeaders, HttpData.wrap(buffer));
        } else {
            return HttpResponse.of(responseHeaders);
        }
    }
Returns a JSON response based on Google APIs.
Please refer to <a href="https://cloud.google.com/apis/design/errors#error_model">Google error model</a>

@param ctx the service context.
@param status the gRPC {@link Status} code.
@param response the gRPC response.

@return the {@link HttpResponse}.
grpc/src/main/java/com/linecorp/armeria/server/grpc/JsonUnframedGrpcErrorHandler.java