private CompletableFuture<Result> send(String method, DocumentId documentId, String operationJson, OperationParameters params) {
        if (closed.get())
            throw new IllegalStateException("Client is closed");

        HttpRequest request = new HttpRequest(method,
                                              getPath(documentId),
                                              getQuery(params, speedTest),
                                              requestHeaders,
                                              operationJson == null ? null : operationJson.getBytes(UTF_8), // TODO: make it bytes all the way?
                                              params.timeout().orElse(maxTimeout),
                                              nanoClock);

        CompletableFuture<Result> promise = new CompletableFuture<>();
        requestStrategy.enqueue(documentId, request)
                       .thenApply(response -> toResult(request, response, documentId))
                       .whenComplete((result, thrown) -> {
                           if (thrown != null) {
                               while (thrown instanceof CompletionException)
                                   thrown = thrown.getCause();

                               promise.completeExceptionally(thrown);
                           }
                           else
                               promise.complete(result);
                       });
        return promise;
    }
HTTP implementation of {@link FeedClient}

@author bjorncs
@author jonmv
vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/HttpFeedClient.java