@SneakyThrows
    private <R> R callController(HttpMethod method, String path,
                                 Function<HttpClientRequest, String> requestMapper,
                                 Function<String, R> responseMapper) {
        verifyActive();

        CompletableFuture<R> resultFuture = new CompletableFuture<>();
        AtomicReference<HttpClientRequest> requestReference = new AtomicReference<>();

        RequestOptions requestOptions = new RequestOptions()
                .setMethod(method)
                .setAbsoluteURI(endpoint + path)
                .setConnectTimeout(connectTimeout)
                .setIdleTimeout(timeout);

        client.request(requestOptions)
                .compose(request -> {
                    requestReference.set(request);
                    String body = requestMapper.apply(request);
                    return request.send((body == null) ? "" : body)
                            .compose(response -> { // must be inside to eliminate race condition for response.body()
                                if (response.statusCode() != 200) {
                                    throw new IllegalStateException("Controller API error. Code: " + response.statusCode());
                                }

                                return response.body();
                            });
                })
                .map(buffer -> {
                    String body = buffer.toString(StandardCharsets.UTF_8);
                    return responseMapper.apply(body);
                })
                .onSuccess(resultFuture::complete)
                .onFailure(resultFuture::completeExceptionally);

        try {
            return resultFuture.get(timeout, TimeUnit.MILLISECONDS);
        } catch (Throwable e) {
            if (e instanceof TimeoutException) {
                HttpClientRequest request = requestReference.get();

                if (request != null) {
                    request.reset();
                }
            }

            if (e instanceof ExecutionException) {
                e = e.getCause();
            }

            throw e;
        }
    }
A web client to Application Controller Web Service that manages deployments for applications with functions.
server/src/main/java/com/epam/aidial/core/server/service/ApplicationOperatorService.java