private HttpResponse<byte[]> send(HttpRequest request, int attempts) {
        if (attempts < 1)
            throw new IllegalStateException("Programming error, attempts must be at least 1");

        UncheckedIOException thrown = null;
        for (int attempt = 1, connectionRetries = 3; attempt <= attempts; attempt++) {
            try {
                HttpResponse<byte[]> response = client.send(request, ofByteArray());
                if (response.statusCode() / 100 == 2)
                    return response;

                Inspector rootObject = toSlime(response.body()).get();
                String message = response.request() + " returned code " + response.statusCode() +
                                 (rootObject.field("error-code").valid() ? " (" + rootObject.field("error-code").asString() + ")" : "") +
                                 ": " + rootObject.field("message").asString();

                if (response.statusCode() == 403)
                    throw new IllegalArgumentException("Access denied for " + request + ": " + message);

                if (response.statusCode() / 100 == 4)
                    throw new IllegalArgumentException("Bad request for " + request + ": " + message);

                throw new IOException(message);

            }
            catch (IOException e) { // Catches the above, and timeout exceptions from the client.
                if (thrown == null)
                    thrown = new UncheckedIOException("Failed " + request + ": " + e, e);
                else
                    thrown.addSuppressed(e);

                if (attempt < 10)
                    try {
                        Thread.sleep(10 << attempt);
                    }
                    catch (InterruptedException f) {
                        throw new RuntimeException(f);
                    }

                if (e instanceof HttpConnectTimeoutException && --connectionRetries > 0) --attempt;
            }
            catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        throw thrown;
    }
Returns a response with a 2XX status code, after the specified number of attempts, or throws.
hosted-api/src/main/java/ai/vespa/hosted/api/ControllerHttpClient.java