You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ja...@apache.org on 2022/03/09 07:22:30 UTC

[camel-quarkus] branch main updated: Add Azure Core HTTP Client Vert.x extension

This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new 75a4b1d  Add Azure Core HTTP Client Vert.x extension
75a4b1d is described below

commit 75a4b1d6d4132b12f610c774a20346cb930f8755
Author: James Netherton <ja...@gmail.com>
AuthorDate: Tue Mar 8 07:19:23 2022 +0000

    Add Azure Core HTTP Client Vert.x extension
    
    Fixes #2196
---
 extensions-jvm/azure-cosmosdb/deployment/pom.xml   |   2 +-
 extensions-jvm/azure-cosmosdb/runtime/pom.xml      |   8 +-
 extensions-jvm/azure-servicebus/deployment/pom.xml |   4 +
 extensions-jvm/azure-servicebus/runtime/pom.xml    |  10 +
 .../azure-storage-datalake/deployment/pom.xml      |   2 +-
 .../azure-storage-datalake/runtime/pom.xml         |   8 +-
 .../deployment}/pom.xml                            |  72 +++--
 .../vertx/AzureCoreHttpClientVertxProcessor.java   |  31 ++
 .../azure/core/http/vertx/DeadlockTests.java       |  89 ++++++
 .../http/vertx/VertxHttpClientBuilderTests.java    | 181 ++++++++++++
 .../http/vertx/VertxHttpClientHttpClientTests.java |  55 ++++
 .../http/vertx/VertxHttpClientProviderTests.java   | 113 ++++++++
 .../vertx/VertxHttpClientResponseTransformer.java  |  56 ++++
 .../http/vertx/VertxHttpClientRestProxyTests.java  |  63 ++++
 ...VertxHttpClientRestProxyWithHttpProxyTests.java |  86 ++++++
 .../http/vertx/VertxHttpClientTestResource.java    |  73 +++++
 .../core/http/vertx/VertxHttpClientTests.java      | 317 +++++++++++++++++++++
 .../deployment/src/test/resources/upload.txt       |   1 +
 .../azure-core-http-client-vertx/pom.xml           |  37 +++
 .../runtime/pom.xml                                |  22 +-
 .../core/http/vertx/BufferedVertxHttpResponse.java |  72 +++++
 .../core/http/vertx/VertxHttpAsyncResponse.java    |  52 ++++
 .../azure/core/http/vertx/VertxHttpClient.java     | 133 +++++++++
 .../core/http/vertx/VertxHttpClientBuilder.java    | 250 ++++++++++++++++
 .../core/http/vertx/VertxHttpClientProvider.java   |  76 +++++
 .../azure/core/http/vertx/VertxHttpRequest.java    |  37 +++
 .../azure/core/http/vertx/VertxHttpResponse.java   |  73 +++++
 .../core/http/vertx/VertxHttpResponseHandler.java  |  59 ++++
 .../main/resources/META-INF/quarkus-extension.yaml |  27 ++
 .../com.azure.core.http.HttpClientProvider         |   1 +
 extensions-support/azure-core/deployment/pom.xml   |   6 +-
 extensions-support/azure-core/runtime/pom.xml      |  12 +-
 extensions-support/pom.xml                         |   1 +
 extensions/azure-eventhubs/runtime/pom.xml         |   6 +
 extensions/azure-storage-blob/deployment/pom.xml   |   2 +-
 extensions/azure-storage-blob/runtime/pom.xml      |   8 +-
 extensions/azure-storage-queue/deployment/pom.xml  |   2 +-
 extensions/azure-storage-queue/runtime/pom.xml     |   8 +-
 .../storage/blob/it/AzureStorageBlobTest.java      |  39 +--
 pom.xml                                            |   2 +
 poms/bom-test/pom.xml                              |  20 ++
 poms/bom/pom.xml                                   |  10 +
 42 files changed, 2062 insertions(+), 64 deletions(-)

diff --git a/extensions-jvm/azure-cosmosdb/deployment/pom.xml b/extensions-jvm/azure-cosmosdb/deployment/pom.xml
index 1c7501c..2af136b 100644
--- a/extensions-jvm/azure-cosmosdb/deployment/pom.xml
+++ b/extensions-jvm/azure-cosmosdb/deployment/pom.xml
@@ -36,7 +36,7 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-azure-core-deployment</artifactId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx-deployment</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
diff --git a/extensions-jvm/azure-cosmosdb/runtime/pom.xml b/extensions-jvm/azure-cosmosdb/runtime/pom.xml
index 37f26bf..6302c56 100644
--- a/extensions-jvm/azure-cosmosdb/runtime/pom.xml
+++ b/extensions-jvm/azure-cosmosdb/runtime/pom.xml
@@ -53,11 +53,17 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-azure-core</artifactId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-azure-cosmosdb</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.azure</groupId>
+                    <artifactId>azure-core-http-netty</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
     </dependencies>
 
diff --git a/extensions-jvm/azure-servicebus/deployment/pom.xml b/extensions-jvm/azure-servicebus/deployment/pom.xml
index fe1d73e..c33bc7f 100644
--- a/extensions-jvm/azure-servicebus/deployment/pom.xml
+++ b/extensions-jvm/azure-servicebus/deployment/pom.xml
@@ -38,6 +38,10 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx-deployment</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-azure-servicebus</artifactId>
         </dependency>
     </dependencies>
diff --git a/extensions-jvm/azure-servicebus/runtime/pom.xml b/extensions-jvm/azure-servicebus/runtime/pom.xml
index 7ed8115..a4d0a9e 100644
--- a/extensions-jvm/azure-servicebus/runtime/pom.xml
+++ b/extensions-jvm/azure-servicebus/runtime/pom.xml
@@ -54,8 +54,18 @@
             <artifactId>camel-quarkus-core</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-azure-servicebus</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.azure</groupId>
+                    <artifactId>azure-core-http-netty</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
     </dependencies>
 
diff --git a/extensions-jvm/azure-storage-datalake/deployment/pom.xml b/extensions-jvm/azure-storage-datalake/deployment/pom.xml
index 8758926..4628cc2 100644
--- a/extensions-jvm/azure-storage-datalake/deployment/pom.xml
+++ b/extensions-jvm/azure-storage-datalake/deployment/pom.xml
@@ -36,7 +36,7 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-azure-core-deployment</artifactId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx-deployment</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
diff --git a/extensions-jvm/azure-storage-datalake/runtime/pom.xml b/extensions-jvm/azure-storage-datalake/runtime/pom.xml
index ae64da2..3f75f0d 100644
--- a/extensions-jvm/azure-storage-datalake/runtime/pom.xml
+++ b/extensions-jvm/azure-storage-datalake/runtime/pom.xml
@@ -53,11 +53,17 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-azure-core</artifactId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-azure-storage-datalake</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.azure</groupId>
+                    <artifactId>azure-core-http-netty</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
     </dependencies>
 
diff --git a/extensions-support/azure-core/runtime/pom.xml b/extensions-support/azure-core-http-client-vertx/deployment/pom.xml
similarity index 55%
copy from extensions-support/azure-core/runtime/pom.xml
copy to extensions-support/azure-core-http-client-vertx/deployment/pom.xml
index 701cd25..5e9d670 100644
--- a/extensions-support/azure-core/runtime/pom.xml
+++ b/extensions-support/azure-core-http-client-vertx/deployment/pom.xml
@@ -21,24 +21,19 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus-support-azure-core-parent</artifactId>
+        <artifactId>camel-quarkus-support-azure-core-http-client-vertx-parent</artifactId>
         <version>2.8.0-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
-    <artifactId>camel-quarkus-support-azure-core</artifactId>
-    <name>Camel Quarkus :: Support :: Azure Core :: Runtime</name>
-
-    <properties>
-        <camel.quarkus.jvmSince>1.7.0</camel.quarkus.jvmSince>
-        <camel.quarkus.nativeSince>1.7.0</camel.quarkus.nativeSince>
-    </properties>
+    <artifactId>camel-quarkus-support-azure-core-http-client-vertx-deployment</artifactId>
+    <name>Camel Quarkus :: Support :: Azure Core HTTP Client Vert.x :: Deployment</name>
 
     <dependencyManagement>
         <dependencies>
             <dependency>
                 <groupId>org.apache.camel.quarkus</groupId>
-                <artifactId>camel-quarkus-bom</artifactId>
+                <artifactId>camel-quarkus-bom-test</artifactId>
                 <version>${project.version}</version>
                 <type>pom</type>
                 <scope>import</scope>
@@ -49,29 +44,73 @@
     <dependencies>
         <dependency>
             <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-core</artifactId>
+            <artifactId>quarkus-core-deployment</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-vertx-deployment</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-jackson-dataformat-xml</artifactId>
+            <artifactId>camel-quarkus-support-azure-core-deployment</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-reactor-netty</artifactId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx</artifactId>
+        </dependency>
+
+
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5-internal</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.testcontainers</groupId>
+            <artifactId>testcontainers</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-integration-wiremock-support</artifactId>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.hamcrest</groupId>
+                    <artifactId>hamcrest-core</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+
+        <!-- Azure core test support -->
+        <dependency>
             <groupId>com.azure</groupId>
             <artifactId>azure-core</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.azure</groupId>
+            <artifactId>azure-core-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.azure</groupId>
+            <artifactId>azure-core-test</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.projectreactor</groupId>
+            <artifactId>reactor-test</artifactId>
+            <scope>test</scope>
         </dependency>
     </dependencies>
 
     <build>
         <plugins>
             <plugin>
-                <groupId>io.quarkus</groupId>
-                <artifactId>quarkus-bootstrap-maven-plugin</artifactId>
-            </plugin>
-            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <configuration>
@@ -86,4 +125,5 @@
             </plugin>
         </plugins>
     </build>
+
 </project>
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/AzureCoreHttpClientVertxProcessor.java b/extensions-support/azure-core-http-client-vertx/deployment/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/AzureCoreHttpClientVertxProcessor.java
new file mode 100644
index 0000000..db0972b
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/AzureCoreHttpClientVertxProcessor.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import io.netty.handler.ssl.OpenSsl;
+import io.quarkus.deployment.annotations.BuildProducer;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
+
+public class AzureCoreHttpClientVertxProcessor {
+
+    @BuildStep
+    void runtimeInitializedClasses(BuildProducer<RuntimeInitializedClassBuildItem> runtimeInitializedClasses) {
+        runtimeInitializedClasses.produce(new RuntimeInitializedClassBuildItem(OpenSsl.class.getName()));
+        runtimeInitializedClasses.produce(new RuntimeInitializedClassBuildItem("io.netty.internal.tcnative.SSL"));
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/DeadlockTests.java b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/DeadlockTests.java
new file mode 100644
index 0000000..18237b4
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/DeadlockTests.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.security.SecureRandom;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpMethod;
+import com.azure.core.http.HttpRequest;
+import com.azure.core.util.FluxUtil;
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
+import io.quarkus.test.QuarkusUnitTest;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+public class DeadlockTests {
+
+    @RegisterExtension
+    static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
+            .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
+
+    private static final String GET_ENDPOINT = "/get";
+
+    private WireMockServer server;
+    private byte[] expectedGetBytes;
+
+    @BeforeEach
+    public void configureWireMockServer() {
+        expectedGetBytes = new byte[10 * 1024 * 1024];
+        new SecureRandom().nextBytes(expectedGetBytes);
+
+        server = new WireMockServer(WireMockConfiguration.options()
+                .dynamicPort()
+                .disableRequestJournal()
+                .gzipDisabled(true));
+
+        server.stubFor(WireMock.get(GET_ENDPOINT).willReturn(WireMock.aResponse().withBody(expectedGetBytes)));
+
+        server.start();
+    }
+
+    @AfterEach
+    public void shutdownWireMockServer() {
+        if (server != null) {
+            server.shutdown();
+        }
+    }
+
+    @Test
+    public void attemptToDeadlock() {
+        HttpClient httpClient = new VertxHttpClientProvider().createInstance();
+
+        String endpoint = server.baseUrl() + GET_ENDPOINT;
+
+        for (int i = 0; i < 100; i++) {
+            StepVerifier.create(httpClient.send(new HttpRequest(HttpMethod.GET, endpoint))
+                    .flatMap(response -> FluxUtil.collectBytesInByteBufferStream(response.getBody())
+                            .zipWith(Mono.just(response.getStatusCode()))))
+                    .assertNext(responseTuple -> {
+                        Assertions.assertEquals(200, responseTuple.getT2());
+                        Assertions.assertArrayEquals(expectedGetBytes, responseTuple.getT1());
+                    })
+                    .verifyComplete();
+        }
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientBuilderTests.java b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientBuilderTests.java
new file mode 100644
index 0000000..03f6099
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientBuilderTests.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.net.InetSocketAddress;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpMethod;
+import com.azure.core.http.HttpRequest;
+import com.azure.core.http.ProxyOptions;
+import com.azure.core.util.Configuration;
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
+import io.vertx.core.Vertx;
+import io.vertx.ext.web.client.WebClientOptions;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+import reactor.test.StepVerifier;
+
+import static org.apache.camel.quarkus.support.azure.core.http.vertx.VertxHttpClientTestResource.PROXY_PASSWORD;
+import static org.apache.camel.quarkus.support.azure.core.http.vertx.VertxHttpClientTestResource.PROXY_USER;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * Tests {@link VertxHttpClientBuilder}.
+ */
+public class VertxHttpClientBuilderTests {
+    private static final String COOKIE_VALIDATOR_PATH = "/cookieValidator";
+    private static final String DEFAULT_PATH = "/default";
+    private static final String DISPATCHER_PATH = "/dispatcher";
+
+    private static final WireMockServer server = new WireMockServer(
+            WireMockConfiguration.options().dynamicPort().disableRequestJournal());
+    private static final Vertx vertx = Vertx.vertx();
+
+    private static String defaultUrl;
+
+    @BeforeAll
+    public static void setupWireMock() {
+        // Mocked endpoint to test building a client with a prebuilt client.
+        server.stubFor(WireMock.get(COOKIE_VALIDATOR_PATH).withCookie("test", WireMock.matching("success"))
+                .willReturn(WireMock.aResponse().withStatus(200)));
+
+        // Mocked endpoint to test building a client with a timeout.
+        server.stubFor(WireMock.get(DEFAULT_PATH).willReturn(WireMock.aResponse().withStatus(200)));
+
+        // Mocked endpoint to test building a client with a dispatcher and uses a delayed response.
+        server.stubFor(WireMock.get(DISPATCHER_PATH).willReturn(WireMock.aResponse().withStatus(200)
+                .withFixedDelay(5000)));
+
+        server.start();
+
+        defaultUrl = "http://localhost:" + server.port() + DEFAULT_PATH;
+    }
+
+    @AfterAll
+    public static void afterAll() throws InterruptedException {
+        if (server.isRunning()) {
+            server.shutdown();
+        }
+        CountDownLatch latch = new CountDownLatch(1);
+        vertx.close(x -> latch.countDown());
+        latch.await();
+    }
+
+    @Test
+    public void buildWithConfigurationNone() {
+        HttpClient client = new VertxHttpClientBuilder(vertx)
+                .configuration(Configuration.NONE)
+                .build();
+        try {
+            StepVerifier.create(client.send(new HttpRequest(HttpMethod.GET, defaultUrl)))
+                    .assertNext(response -> assertEquals(200, response.getStatusCode()))
+                    .verifyComplete();
+        } finally {
+            ((VertxHttpClient) client).close();
+        }
+    }
+
+    @Test
+    public void buildWithDefaultConnectionOptions() {
+        WebClientOptions options = new WebClientOptions();
+
+        HttpClient client = new VertxHttpClientBuilder(vertx)
+                .webClientOptions(options)
+                .build();
+
+        try {
+            StepVerifier.create(client.send(new HttpRequest(HttpMethod.GET, defaultUrl)))
+                    .assertNext(response -> assertEquals(200, response.getStatusCode()))
+                    .verifyComplete();
+
+            assertEquals(options.getConnectTimeout(), 10000);
+            assertEquals(options.getIdleTimeout(), 60);
+            assertEquals(options.getReadIdleTimeout(), 60);
+            assertEquals(options.getWriteIdleTimeout(), 60);
+        } finally {
+            ((VertxHttpClient) client).close();
+        }
+    }
+
+    @Test
+    public void buildWithConnectionOptions() {
+        WebClientOptions options = new WebClientOptions();
+
+        HttpClient client = new VertxHttpClientBuilder(vertx)
+                .webClientOptions(options)
+                .connectTimeout(Duration.ofSeconds(10))
+                .idleTimeout(Duration.ofSeconds(20))
+                .readIdleTimeout(Duration.ofSeconds(30))
+                .writeIdleTimeout(Duration.ofSeconds(40))
+                .build();
+
+        try {
+            StepVerifier.create(client.send(new HttpRequest(HttpMethod.GET, defaultUrl)))
+                    .assertNext(response -> assertEquals(200, response.getStatusCode()))
+                    .verifyComplete();
+
+            assertEquals(options.getConnectTimeout(), 10000);
+            assertEquals(options.getIdleTimeout(), 20);
+            assertEquals(options.getReadIdleTimeout(), 30);
+            assertEquals(options.getWriteIdleTimeout(), 40);
+        } finally {
+            ((VertxHttpClient) client).close();
+        }
+    }
+
+    @ParameterizedTest
+    @EnumSource(ProxyOptions.Type.class)
+    public void allProxyOptions(ProxyOptions.Type type) {
+        WebClientOptions options = new WebClientOptions();
+        InetSocketAddress address = new InetSocketAddress("localhost", 8888);
+        ProxyOptions proxyOptions = new ProxyOptions(type, address);
+        proxyOptions.setCredentials(PROXY_USER, PROXY_PASSWORD);
+        proxyOptions.setNonProxyHosts("foo.*|*bar.com|microsoft.com");
+
+        HttpClient client = new VertxHttpClientBuilder(vertx)
+                .webClientOptions(options)
+                .proxy(proxyOptions)
+                .build();
+
+        try {
+            io.vertx.core.net.ProxyOptions vertxProxyOptions = options.getProxyOptions();
+            assertEquals(vertxProxyOptions.getHost(), address.getHostName());
+            assertEquals(vertxProxyOptions.getPort(), address.getPort());
+            assertEquals(vertxProxyOptions.getType().name(), type.name());
+            assertEquals(vertxProxyOptions.getUsername(), PROXY_USER);
+            assertEquals(vertxProxyOptions.getPassword(), PROXY_PASSWORD);
+
+            List<String> proxyHosts = new ArrayList<>();
+            proxyHosts.add("foo*");
+            proxyHosts.add(".*bar.com");
+            proxyHosts.add("microsoft.com");
+            assertEquals(proxyHosts, options.getNonProxyHosts());
+        } finally {
+            ((VertxHttpClient) client).close();
+        }
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientHttpClientTests.java b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientHttpClientTests.java
new file mode 100644
index 0000000..67dae66
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientHttpClientTests.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.util.concurrent.CountDownLatch;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.test.HttpClientTestsWireMockServer;
+import com.azure.core.test.http.HttpClientTests;
+import com.github.tomakehurst.wiremock.WireMockServer;
+import io.vertx.core.Vertx;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+
+public class VertxHttpClientHttpClientTests extends HttpClientTests {
+    private static final WireMockServer server = HttpClientTestsWireMockServer.getHttpClientTestsServer();
+    private static final Vertx vertx = Vertx.vertx();
+
+    @BeforeAll
+    public static void getWireMockServer() {
+        server.start();
+    }
+
+    @AfterAll
+    public static void afterAll() throws InterruptedException {
+        server.shutdown();
+        CountDownLatch latch = new CountDownLatch(1);
+        vertx.close(x -> latch.countDown());
+        latch.await();
+    }
+
+    @Override
+    protected int getWireMockPort() {
+        return server.port();
+    }
+
+    @Override
+    protected HttpClient createHttpClient() {
+        return new VertxHttpClientBuilder(vertx).build();
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientProviderTests.java b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientProviderTests.java
new file mode 100644
index 0000000..402d154
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientProviderTests.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.net.InetSocketAddress;
+import java.time.Duration;
+
+import com.azure.core.http.ProxyOptions;
+import com.azure.core.util.Configuration;
+import com.azure.core.util.HttpClientOptions;
+import io.quarkus.test.QuarkusUnitTest;
+import io.vertx.ext.web.client.WebClientOptions;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * Tests {@link VertxHttpClientProvider}.
+ */
+
+public class VertxHttpClientProviderTests {
+
+    @RegisterExtension
+    static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
+            .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
+
+    @Test
+    public void nullOptionsReturnsBaseClient() {
+        VertxHttpClient httpClient = (VertxHttpClient) new VertxHttpClientProvider()
+                .createInstance(null);
+
+        ProxyOptions environmentProxy = ProxyOptions.fromConfiguration(Configuration.getGlobalConfiguration());
+        WebClientOptions options = httpClient.getWebClientOptions();
+        io.vertx.core.net.ProxyOptions proxyOptions = options.getProxyOptions();
+        if (environmentProxy == null) {
+            assertNull(proxyOptions);
+        } else {
+            assertNotNull(proxyOptions);
+            assertEquals(environmentProxy.getAddress().getHostName(), proxyOptions.getHost());
+        }
+    }
+
+    @Test
+    public void defaultOptionsReturnsBaseClient() {
+        VertxHttpClient httpClient = (VertxHttpClient) new VertxHttpClientProvider()
+                .createInstance(new HttpClientOptions());
+
+        ProxyOptions environmentProxy = ProxyOptions.fromConfiguration(Configuration.getGlobalConfiguration());
+        WebClientOptions options = httpClient.getWebClientOptions();
+        io.vertx.core.net.ProxyOptions proxyOptions = options.getProxyOptions();
+        if (environmentProxy == null) {
+            assertNull(proxyOptions);
+        } else {
+            assertNotNull(proxyOptions);
+            assertEquals(environmentProxy.getAddress().getHostName(), proxyOptions.getHost());
+        }
+    }
+
+    @Test
+    public void optionsWithAProxy() {
+        ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("localhost", 8888));
+        proxyOptions.setNonProxyHosts("foo.*|bar.*|cheese.com|wine.org");
+
+        HttpClientOptions clientOptions = new HttpClientOptions().setProxyOptions(proxyOptions);
+
+        VertxHttpClient httpClient = (VertxHttpClient) new VertxHttpClientProvider()
+                .createInstance(clientOptions);
+
+        WebClientOptions options = httpClient.getWebClientOptions();
+        io.vertx.core.net.ProxyOptions vertxProxyOptions = options.getProxyOptions();
+        assertNotNull(vertxProxyOptions);
+        assertEquals(proxyOptions.getAddress().getHostName(), vertxProxyOptions.getHost());
+        assertEquals(proxyOptions.getAddress().getPort(), vertxProxyOptions.getPort());
+        assertEquals(proxyOptions.getType().name(), vertxProxyOptions.getType().name());
+    }
+
+    @Test
+    public void optionsWithTimeouts() {
+        long expectedTimeout = 15000;
+        Duration timeout = Duration.ofMillis(expectedTimeout);
+        HttpClientOptions clientOptions = new HttpClientOptions()
+                .setWriteTimeout(timeout)
+                .setResponseTimeout(timeout)
+                .setReadTimeout(timeout);
+
+        VertxHttpClient httpClient = (VertxHttpClient) new VertxHttpClientProvider()
+                .createInstance(clientOptions);
+
+        WebClientOptions options = httpClient.getWebClientOptions();
+
+        assertEquals(timeout.getSeconds(), options.getWriteIdleTimeout());
+        assertEquals(timeout.getSeconds(), options.getReadIdleTimeout());
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientResponseTransformer.java b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientResponseTransformer.java
new file mode 100644
index 0000000..fe7aa1c
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientResponseTransformer.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import com.github.tomakehurst.wiremock.common.FileSource;
+import com.github.tomakehurst.wiremock.extension.Parameters;
+import com.github.tomakehurst.wiremock.extension.ResponseTransformer;
+import com.github.tomakehurst.wiremock.http.Request;
+import com.github.tomakehurst.wiremock.http.Response;
+
+import static org.apache.camel.quarkus.support.azure.core.http.vertx.VertxHttpClientTests.RETURN_HEADERS_AS_IS_PATH;
+
+/**
+ * Mock response transformer used to test {@link VertxHttpClient}.
+ */
+public class VertxHttpClientResponseTransformer extends ResponseTransformer {
+    public static final String NAME = "vertx-http-client-response-transformer";
+
+    @Override
+    public Response transform(Request request, Response response, FileSource fileSource, Parameters parameters) {
+        String url = request.getUrl();
+
+        if (RETURN_HEADERS_AS_IS_PATH.equalsIgnoreCase(url)) {
+            return Response.response()
+                    .status(200)
+                    .headers(request.getHeaders())
+                    .build();
+        }
+
+        return response;
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public boolean applyGlobally() {
+        return false;
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientRestProxyTests.java b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientRestProxyTests.java
new file mode 100644
index 0000000..153d840
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientRestProxyTests.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import javax.inject.Inject;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.test.RestProxyTestsWireMockServer;
+import com.azure.core.test.implementation.RestProxyTests;
+import com.github.tomakehurst.wiremock.WireMockServer;
+import io.quarkus.test.QuarkusUnitTest;
+import io.vertx.core.Vertx;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class VertxHttpClientRestProxyTests extends RestProxyTests {
+    private final static WireMockServer server = RestProxyTestsWireMockServer.getRestProxyTestsServer();
+
+    @RegisterExtension
+    static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
+            .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
+                    .addAsResource("upload.txt", "upload.txt"));
+
+    @Inject
+    Vertx vertx;
+
+    @BeforeAll
+    public static void getWireMockServer() {
+        server.start();
+    }
+
+    @AfterAll
+    public static void shutdownWireMockServer() {
+        server.shutdown();
+    }
+
+    @Override
+    protected int getWireMockPort() {
+        return server.port();
+    }
+
+    @Override
+    protected HttpClient createHttpClient() {
+        return new VertxHttpClientBuilder(vertx).build();
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientRestProxyWithHttpProxyTests.java b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientRestProxyWithHttpProxyTests.java
new file mode 100644
index 0000000..748ede8
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientRestProxyWithHttpProxyTests.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.net.InetSocketAddress;
+
+import javax.inject.Inject;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.ProxyOptions;
+import com.azure.core.test.RestProxyTestsWireMockServer;
+import com.azure.core.test.implementation.RestProxyTests;
+import com.github.tomakehurst.wiremock.WireMockServer;
+import io.quarkus.test.QuarkusUnitTest;
+import io.quarkus.test.common.QuarkusTestResource;
+import io.vertx.core.Vertx;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static org.apache.camel.quarkus.support.azure.core.http.vertx.VertxHttpClientTestResource.PROXY_PASSWORD;
+import static org.apache.camel.quarkus.support.azure.core.http.vertx.VertxHttpClientTestResource.PROXY_USER;
+
+@QuarkusTestResource(VertxHttpClientTestResource.class)
+public class VertxHttpClientRestProxyWithHttpProxyTests extends RestProxyTests {
+    private static WireMockServer server;
+
+    @RegisterExtension
+    static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
+            .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
+                    .addAsResource("upload.txt", "upload.txt"));
+
+    @Inject
+    Vertx vertx;
+
+    @BeforeAll
+    public static void getWireMockServer() {
+        server = RestProxyTestsWireMockServer.getRestProxyTestsServer();
+        server.start();
+    }
+
+    @AfterAll
+    public static void shutdownWireMockServer() {
+        if (server != null) {
+            server.shutdown();
+        }
+    }
+
+    @Override
+    protected int getWireMockPort() {
+        return server.port();
+    }
+
+    @Override
+    protected HttpClient createHttpClient() {
+        Config config = ConfigProvider.getConfig();
+        String proxyHost = config.getValue("tiny.proxy.host", String.class);
+        int proxyPort = config.getValue("tiny.proxy.port", int.class);
+
+        InetSocketAddress address = new InetSocketAddress(proxyHost, proxyPort);
+        ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP, address);
+        proxyOptions.setCredentials(PROXY_USER, PROXY_PASSWORD);
+
+        return new VertxHttpClientBuilder(vertx)
+                .proxy(proxyOptions)
+                .build();
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientTestResource.java b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientTestResource.java
new file mode 100644
index 0000000..2a54ab7
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientTestResource.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+import org.apache.commons.lang3.SystemUtils;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
+
+public class VertxHttpClientTestResource implements QuarkusTestResourceLifecycleManager {
+
+    public static final String PROXY_USER = "admin";
+    public static final String PROXY_PASSWORD = "p4ssw0rd";
+
+    private static final DockerImageName TINY_PROXY_IMAGE_NAME = DockerImageName.parse("monokal/tinyproxy");
+    private static final Integer TINY_PROXY_PORT = 8888;
+    private GenericContainer container;
+
+    @Override
+    public Map<String, String> start() {
+        String host;
+        int port;
+
+        container = new GenericContainer(TINY_PROXY_IMAGE_NAME)
+                .withEnv("BASIC_AUTH_USER", PROXY_USER)
+                .withEnv("BASIC_AUTH_PASSWORD", PROXY_PASSWORD)
+                .withCommand("ANY")
+                .waitingFor(Wait.forListeningPort());
+
+        if (SystemUtils.IS_OS_LINUX) {
+            container.withNetworkMode("host");
+            port = TINY_PROXY_PORT;
+            host = "localhost";
+        } else {
+            container.withNetworkMode("bridge")
+                    .withExposedPorts(TINY_PROXY_PORT);
+            port = container.getMappedPort(TINY_PROXY_PORT);
+            host = "host.docker.internal";
+        }
+
+        container.start();
+
+        Map<String, String> options = new HashMap<>();
+        options.put("tiny.proxy.host", host);
+        options.put("tiny.proxy.port", String.valueOf(port));
+        return options;
+    }
+
+    @Override
+    public void stop() {
+        if (container != null) {
+            container.stop();
+        }
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientTests.java b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientTests.java
new file mode 100644
index 0000000..ba72040
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/test/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientTests.java
@@ -0,0 +1,317 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+import javax.inject.Inject;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpHeader;
+import com.azure.core.http.HttpHeaders;
+import com.azure.core.http.HttpMethod;
+import com.azure.core.http.HttpRequest;
+import com.azure.core.http.HttpResponse;
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
+import io.quarkus.test.QuarkusUnitTest;
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxException;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import reactor.core.scheduler.Schedulers;
+import reactor.test.StepVerifier;
+import reactor.test.StepVerifierOptions;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class VertxHttpClientTests {
+    static final String RETURN_HEADERS_AS_IS_PATH = "/returnHeadersAsIs";
+
+    private static final String SHORT_BODY = "hi there";
+    private static final String LONG_BODY = createLongBody();
+
+    private static WireMockServer server;
+
+    @Inject
+    Vertx vertx;
+
+    @RegisterExtension
+    static final QuarkusUnitTest CONFIG = new QuarkusUnitTest()
+            .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
+                    .addClass(VertxHttpClientResponseTransformer.class));
+
+    @BeforeAll
+    public static void beforeClass() {
+        server = new WireMockServer(WireMockConfiguration.options()
+                .extensions(new VertxHttpClientResponseTransformer())
+                .dynamicPort()
+                .disableRequestJournal()
+                .gzipDisabled(true));
+
+        server.stubFor(WireMock.get("/short").willReturn(WireMock.aResponse().withBody(SHORT_BODY)));
+        server.stubFor(WireMock.get("/long").willReturn(WireMock.aResponse().withBody(LONG_BODY)));
+        server.stubFor(WireMock.get("/error").willReturn(WireMock.aResponse().withBody("error").withStatus(500)));
+        server.stubFor(WireMock.post("/shortPost").willReturn(WireMock.aResponse().withBody(SHORT_BODY)));
+        server.stubFor(WireMock.get(RETURN_HEADERS_AS_IS_PATH).willReturn(WireMock.aResponse()
+                .withTransformers(VertxHttpClientResponseTransformer.NAME)));
+
+        server.start();
+    }
+
+    @AfterAll
+    public static void afterClass() {
+        if (server != null) {
+            server.shutdown();
+        }
+    }
+
+    @Test
+    public void testFlowableResponseShortBodyAsByteArrayAsync() {
+        checkBodyReceived(SHORT_BODY, "/short");
+    }
+
+    @Test
+    public void testFlowableResponseLongBodyAsByteArrayAsync() {
+        checkBodyReceived(LONG_BODY, "/long");
+    }
+
+    @Test
+    public void testFlowableWhenServerReturnsBodyAndNoErrorsWhenHttp500Returned() {
+        HttpResponse response = getResponse("/error");
+        assertEquals(500, response.getStatusCode());
+        StepVerifier.create(response.getBodyAsString())
+                .expectNext("error")
+                .expectComplete()
+                .verify(Duration.ofSeconds(20));
+    }
+
+    @Test
+    public void testFlowableBackpressure() {
+        HttpResponse response = getResponse("/long");
+
+        StepVerifierOptions stepVerifierOptions = StepVerifierOptions.create();
+        stepVerifierOptions.initialRequest(0);
+
+        StepVerifier.create(response.getBody(), stepVerifierOptions)
+                .expectNextCount(0)
+                .thenRequest(1)
+                .expectNextCount(1)
+                .thenRequest(3)
+                .expectNextCount(3)
+                .thenRequest(Long.MAX_VALUE)
+                .thenConsumeWhile(ByteBuffer::hasRemaining)
+                .verifyComplete();
+    }
+
+    @Test
+    public void testRequestBodyIsErrorShouldPropagateToResponse() {
+        HttpClient client = new VertxHttpClientProvider().createInstance();
+        HttpRequest request = new HttpRequest(HttpMethod.POST, url(server, "/shortPost"))
+                .setHeader("Content-Length", "123")
+                .setBody(Flux.error(new RuntimeException("boo")));
+
+        StepVerifier.create(client.send(request))
+                .expectErrorMessage("boo")
+                .verify();
+    }
+
+    @Test
+    public void testRequestBodyEndsInErrorShouldPropagateToResponse() {
+        HttpClient client = new VertxHttpClientProvider().createInstance();
+        String contentChunk = "abcdefgh";
+        int repetitions = 1000;
+        HttpRequest request = new HttpRequest(HttpMethod.POST, url(server, "/shortPost"))
+                .setHeader("Content-Length", String.valueOf(contentChunk.length() * (repetitions + 1)))
+                .setBody(Flux.just(contentChunk)
+                        .repeat(repetitions)
+                        .map(s -> ByteBuffer.wrap(s.getBytes(StandardCharsets.UTF_8)))
+                        .concatWith(Flux.error(new RuntimeException("boo"))));
+        StepVerifier.create(client.send(request))
+                .expectErrorMessage("boo")
+                .verify(Duration.ofSeconds(10));
+    }
+
+    @Test
+    public void testServerShutsDownSocketShouldPushErrorToContentFlowable() {
+        Assertions.assertTimeout(Duration.ofMillis(5000), () -> {
+            CountDownLatch latch = new CountDownLatch(1);
+            try (ServerSocket ss = new ServerSocket(0)) {
+                Mono.fromCallable(() -> {
+                    latch.countDown();
+                    Socket socket = ss.accept();
+                    // give the client time to get request across
+                    Thread.sleep(500);
+                    // respond but don't send the complete response
+                    byte[] bytes = new byte[1024];
+                    int n = socket.getInputStream().read(bytes);
+                    System.out.println(new String(bytes, 0, n, StandardCharsets.UTF_8));
+                    String response = "HTTP/1.1 200 OK\r\n" //
+                            + "Content-Type: text/plain\r\n" //
+                            + "Content-Length: 10\r\n" //
+                            + "\r\n" //
+                            + "zi";
+                    OutputStream out = socket.getOutputStream();
+                    out.write(response.getBytes());
+                    out.flush();
+                    // kill the socket with HTTP response body incomplete
+                    socket.close();
+                    return 1;
+                }).subscribeOn(Schedulers.boundedElastic()).subscribe();
+                //
+                latch.await();
+                HttpClient client = new VertxHttpClientBuilder(vertx).build();
+                HttpRequest request = new HttpRequest(HttpMethod.GET,
+                        new URL("http://localhost:" + ss.getLocalPort() + "/ioException"));
+
+                StepVerifier.create(client.send(request))
+                        .verifyError(VertxException.class);
+            }
+        });
+    }
+
+    @Test
+    public void testConcurrentRequests() throws NoSuchAlgorithmException {
+        int numRequests = 100; // 100 = 1GB of data read
+        HttpClient client = new VertxHttpClientProvider().createInstance();
+        byte[] expectedDigest = digest(LONG_BODY);
+        long expectedByteCount = (long) numRequests * LONG_BODY.getBytes(StandardCharsets.UTF_8).length;
+
+        Mono<Long> numBytesMono = Flux.range(1, numRequests)
+                .parallel(10)
+                .runOn(Schedulers.boundedElastic())
+                .flatMap(n -> Mono.fromCallable(() -> getResponse(client, "/long")).flatMapMany(response -> {
+                    MessageDigest md = md5Digest();
+                    return response.getBody()
+                            .doOnNext(buffer -> md.update(buffer.duplicate()))
+                            .doOnComplete(() -> assertArrayEquals(expectedDigest, md.digest(), "wrong digest!"));
+                }))
+                .sequential()
+                .map(buffer -> (long) buffer.remaining())
+                .reduce(Long::sum);
+
+        StepVerifier.create(numBytesMono)
+                .expectNext(expectedByteCount)
+                .expectComplete()
+                .verify(Duration.ofSeconds(60));
+    }
+
+    @Test
+    public void validateHeadersReturnAsIs() {
+        HttpClient client = new VertxHttpClientProvider().createInstance();
+
+        final String singleValueHeaderName = "singleValue";
+        final String singleValueHeaderValue = "value";
+
+        final String multiValueHeaderName = "Multi-value";
+        final List<String> multiValueHeaderValue = Arrays.asList("value1", "value2");
+
+        HttpHeaders headers = new HttpHeaders()
+                .set(singleValueHeaderName, singleValueHeaderValue)
+                .set(multiValueHeaderName, multiValueHeaderValue);
+
+        StepVerifier.create(client.send(new HttpRequest(HttpMethod.GET, url(server, RETURN_HEADERS_AS_IS_PATH),
+                headers, Flux.empty())))
+                .assertNext(response -> {
+                    Assertions.assertEquals(200, response.getStatusCode());
+
+                    HttpHeaders responseHeaders = response.getHeaders();
+                    HttpHeader singleValueHeader = responseHeaders.get(singleValueHeaderName);
+                    assertEquals(singleValueHeaderName, singleValueHeader.getName());
+                    assertEquals(singleValueHeaderValue, singleValueHeader.getValue());
+
+                    HttpHeader multiValueHeader = responseHeaders.get("Multi-value");
+                    assertEquals(multiValueHeaderName, multiValueHeader.getName());
+                })
+                .expectComplete()
+                .verify(Duration.ofSeconds(10));
+    }
+
+    private static MessageDigest md5Digest() {
+        try {
+            return MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static byte[] digest(String s) throws NoSuchAlgorithmException {
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        md.update(s.getBytes(StandardCharsets.UTF_8));
+        return md.digest();
+    }
+
+    private HttpResponse getResponse(String path) {
+        HttpClient client = new VertxHttpClientBuilder(vertx).build();
+        return getResponse(client, path);
+    }
+
+    private static HttpResponse getResponse(HttpClient client, String path) {
+        HttpRequest request = new HttpRequest(HttpMethod.GET, url(server, path));
+        return client.send(request).block();
+    }
+
+    static URL url(WireMockServer server, String path) {
+        try {
+            return new URL("http://localhost:" + server.port() + path);
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static String createLongBody() {
+        StringBuilder builder = new StringBuilder("abcdefghijk".length() * 1000000);
+        for (int i = 0; i < 1000000; i++) {
+            builder.append("abcdefghijk");
+        }
+
+        return builder.toString();
+    }
+
+    private void checkBodyReceived(String expectedBody, String path) {
+        HttpClient client = new VertxHttpClientBuilder(vertx).build();
+        StepVerifier.create(doRequest(client, path).getBodyAsByteArray())
+                .assertNext(bytes -> assertEquals(expectedBody, new String(bytes, StandardCharsets.UTF_8)))
+                .verifyComplete();
+    }
+
+    private HttpResponse doRequest(HttpClient client, String path) {
+        HttpRequest request = new HttpRequest(HttpMethod.GET, url(server, path));
+        return client.send(request).block();
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/deployment/src/test/resources/upload.txt b/extensions-support/azure-core-http-client-vertx/deployment/src/test/resources/upload.txt
new file mode 100644
index 0000000..ff3bb63
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/deployment/src/test/resources/upload.txt
@@ -0,0 +1 @@
+The quick brown fox jumps over the lazy dog
\ No newline at end of file
diff --git a/extensions-support/azure-core-http-client-vertx/pom.xml b/extensions-support/azure-core-http-client-vertx/pom.xml
new file mode 100644
index 0000000..82f4083
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-extensions-support</artifactId>
+        <version>2.8.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>camel-quarkus-support-azure-core-http-client-vertx-parent</artifactId>
+    <name>Camel Quarkus :: Support :: Azure Core HTTP Client Vert.x</name>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>deployment</module>
+        <module>runtime</module>
+    </modules>
+</project>
diff --git a/extensions-support/azure-core/runtime/pom.xml b/extensions-support/azure-core-http-client-vertx/runtime/pom.xml
similarity index 81%
copy from extensions-support/azure-core/runtime/pom.xml
copy to extensions-support/azure-core-http-client-vertx/runtime/pom.xml
index 701cd25..6a86758 100644
--- a/extensions-support/azure-core/runtime/pom.xml
+++ b/extensions-support/azure-core-http-client-vertx/runtime/pom.xml
@@ -21,17 +21,17 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus-support-azure-core-parent</artifactId>
+        <artifactId>camel-quarkus-support-azure-core-http-client-vertx-parent</artifactId>
         <version>2.8.0-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
-    <artifactId>camel-quarkus-support-azure-core</artifactId>
-    <name>Camel Quarkus :: Support :: Azure Core :: Runtime</name>
+    <artifactId>camel-quarkus-support-azure-core-http-client-vertx</artifactId>
+    <name>Camel Quarkus :: Support :: Azure Core HTTP Client Vert.x :: Runtime</name>
 
     <properties>
-        <camel.quarkus.jvmSince>1.7.0</camel.quarkus.jvmSince>
-        <camel.quarkus.nativeSince>1.7.0</camel.quarkus.nativeSince>
+        <camel.quarkus.jvmSince>2.8.0</camel.quarkus.jvmSince>
+        <camel.quarkus.nativeSince>2.8.0</camel.quarkus.nativeSince>
     </properties>
 
     <dependencyManagement>
@@ -52,17 +52,21 @@
             <artifactId>quarkus-core</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-jackson-dataformat-xml</artifactId>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-vertx</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-reactor-netty</artifactId>
+            <groupId>io.vertx</groupId>
+            <artifactId>vertx-web-client</artifactId>
         </dependency>
         <dependency>
             <groupId>com.azure</groupId>
             <artifactId>azure-core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-support-azure-core</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/BufferedVertxHttpResponse.java b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/BufferedVertxHttpResponse.java
new file mode 100644
index 0000000..344251f
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/BufferedVertxHttpResponse.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+import com.azure.core.http.HttpRequest;
+import com.azure.core.http.HttpResponse;
+import io.vertx.core.buffer.Buffer;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public final class BufferedVertxHttpResponse extends VertxHttpAsyncResponse {
+
+    private final Buffer body;
+
+    BufferedVertxHttpResponse(HttpRequest request, io.vertx.ext.web.client.HttpResponse response, Buffer body) {
+        super(request, response);
+        this.body = body;
+    }
+
+    @Override
+    public Flux<ByteBuffer> getBody() {
+        return Flux.defer(() -> {
+            if (this.body == null || this.body.length() == 0) {
+                return Flux.empty();
+            }
+            return Flux.just(this.body.getByteBuf().nioBuffer());
+        });
+    }
+
+    @Override
+    public Mono<byte[]> getBodyAsByteArray() {
+        return Mono.defer(() -> {
+            if (this.body == null || this.body.length() == 0) {
+                return Mono.empty();
+            }
+            return Mono.just(this.body.getBytes());
+        });
+    }
+
+    @Override
+    public Mono<InputStream> getBodyAsInputStream() {
+        return Mono.defer(() -> {
+            if (this.body == null || this.body.length() == 0) {
+                return Mono.empty();
+            }
+            return Mono.just(new ByteArrayInputStream(this.body.getBytes()));
+        });
+    }
+
+    @Override
+    public HttpResponse buffer() {
+        return this;
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpAsyncResponse.java b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpAsyncResponse.java
new file mode 100644
index 0000000..740c442
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpAsyncResponse.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.nio.ByteBuffer;
+
+import com.azure.core.http.HttpRequest;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.ext.web.client.HttpResponse;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class VertxHttpAsyncResponse extends VertxHttpResponse {
+
+    VertxHttpAsyncResponse(HttpRequest request, HttpResponse response) {
+        super(request, response);
+    }
+
+    @Override
+    public Flux<ByteBuffer> getBody() {
+        Buffer responseBody = getVertxHttpResponse().bodyAsBuffer();
+        if (responseBody == null || responseBody.length() == 0) {
+            return Flux.empty();
+        }
+        return Flux.just(responseBody.getByteBuf().nioBuffer());
+    }
+
+    @Override
+    public Mono<byte[]> getBodyAsByteArray() {
+        return Mono.fromCallable(() -> {
+            Buffer responseBody = getVertxHttpResponse().bodyAsBuffer();
+            if (responseBody == null || responseBody.length() == 0) {
+                return null;
+            }
+            return responseBody.getBytes();
+        });
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClient.java b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClient.java
new file mode 100644
index 0000000..5500a7d
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClient.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.io.Closeable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.util.Objects;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpMethod;
+import com.azure.core.http.HttpRequest;
+import com.azure.core.http.HttpResponse;
+import com.azure.core.util.Context;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.ext.web.client.WebClient;
+import io.vertx.ext.web.client.WebClientOptions;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+/**
+ * {@link HttpClient} implementation for the Vert.x {@link WebClient}.
+ */
+public class VertxHttpClient implements HttpClient, Closeable {
+
+    private final WebClient client;
+    private final WebClientOptions options;
+
+    public VertxHttpClient(WebClient client, WebClientOptions options) {
+        Objects.requireNonNull(client, "client cannot be null");
+        Objects.requireNonNull(client, "options cannot be null");
+        this.client = client;
+        this.options = options;
+    }
+
+    @Override
+    public Mono<HttpResponse> send(HttpRequest request) {
+        return send(request, Context.NONE);
+    }
+
+    @Override
+    public Mono<HttpResponse> send(HttpRequest request, Context context) {
+        boolean eagerlyReadResponse = (boolean) context.getData("azure-eagerly-read-response").orElse(false);
+        return Mono.create(sink -> sink.onRequest(value -> {
+            toVertxHttpRequest(request).subscribe(vertxHttpRequest -> {
+                vertxHttpRequest.send(new VertxHttpResponseHandler(request, sink, eagerlyReadResponse));
+            }, sink::error);
+        }));
+    }
+
+    public void close() {
+        this.client.close();
+    }
+
+    // Exposed for testing
+    public WebClientOptions getWebClientOptions() {
+        return options;
+    }
+
+    private Mono<VertxHttpRequest> toVertxHttpRequest(HttpRequest request) {
+        return Mono.from(convertBodyToBuffer(request))
+                .map(buffer -> {
+                    HttpMethod httpMethod = request.getHttpMethod();
+                    io.vertx.core.http.HttpMethod requestMethod = io.vertx.core.http.HttpMethod.valueOf(httpMethod.name());
+
+                    URL url = request.getUrl();
+                    if (url.getPath().isEmpty()) {
+                        try {
+                            // Azure API documentation states:
+                            //
+                            // The URI must always include the forward slash (/) to separate the host name
+                            // from the path and query portions of the URI.
+                            //
+                            url = new URL(url.getProtocol(), url.getHost(), url.getPort(), "/" + url.getFile());
+                        } catch (MalformedURLException e) {
+                            throw new IllegalStateException(e);
+                        }
+                    }
+
+                    io.vertx.ext.web.client.HttpRequest<Buffer> delegate = client
+                            .requestAbs(requestMethod, url.toString());
+
+                    if (request.getHeaders() != null) {
+                        request.getHeaders()
+                                .stream()
+                                .forEach(httpHeader -> delegate.putHeader(httpHeader.getName(),
+                                        httpHeader.getValuesList()));
+                    }
+
+                    return new VertxHttpRequest(delegate, buffer);
+                });
+    }
+
+    private Mono<Buffer> convertBodyToBuffer(HttpRequest request) {
+        return Mono.using(() -> Buffer.buffer(),
+                buffer -> getBody(request).reduce(buffer, (b, byteBuffer) -> {
+                    for (int i = 0; i < byteBuffer.limit(); i++) {
+                        b.appendByte(byteBuffer.get(i));
+                    }
+                    return b;
+                }), buffer -> buffer.getClass());
+    }
+
+    private Flux<ByteBuffer> getBody(HttpRequest request) {
+        long contentLength = 0;
+        String contentLengthHeader = request.getHeaders().getValue("content-length");
+        if (contentLengthHeader != null) {
+            contentLength = Long.parseLong(contentLengthHeader);
+        }
+
+        Flux<ByteBuffer> body = request.getBody();
+        if (body == null || contentLength <= 0) {
+            body = Flux.just(Buffer.buffer().getByteBuf().nioBuffer());
+        }
+
+        return body;
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientBuilder.java b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientBuilder.java
new file mode 100644
index 0000000..0cb5a14
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientBuilder.java
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.net.InetSocketAddress;
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.ProxyOptions;
+import com.azure.core.util.Configuration;
+import com.azure.core.util.logging.ClientLogger;
+import io.vertx.core.Vertx;
+import io.vertx.core.net.ProxyType;
+import io.vertx.ext.web.client.WebClient;
+import io.vertx.ext.web.client.WebClientOptions;
+
+import static com.azure.core.util.Configuration.PROPERTY_AZURE_REQUEST_CONNECT_TIMEOUT;
+import static com.azure.core.util.Configuration.PROPERTY_AZURE_REQUEST_READ_TIMEOUT;
+import static com.azure.core.util.Configuration.PROPERTY_AZURE_REQUEST_WRITE_TIMEOUT;
+import static com.azure.core.util.CoreUtils.getDefaultTimeoutFromEnvironment;
+
+/**
+ * Builds a {@link VertxHttpClient}.
+ */
+public class VertxHttpClientBuilder {
+
+    private static final long DEFAULT_CONNECT_TIMEOUT;
+    private static final long DEFAULT_WRITE_TIMEOUT;
+    private static final long DEFAULT_READ_TIMEOUT;
+
+    static {
+        ClientLogger logger = new ClientLogger(VertxHttpClientBuilder.class);
+        Configuration configuration = Configuration.getGlobalConfiguration();
+        DEFAULT_CONNECT_TIMEOUT = getDefaultTimeoutFromEnvironment(configuration,
+                PROPERTY_AZURE_REQUEST_CONNECT_TIMEOUT, Duration.ofSeconds(10), logger).toMillis();
+        DEFAULT_WRITE_TIMEOUT = getDefaultTimeoutFromEnvironment(configuration, PROPERTY_AZURE_REQUEST_WRITE_TIMEOUT,
+                Duration.ofSeconds(60), logger).toSeconds();
+        DEFAULT_READ_TIMEOUT = getDefaultTimeoutFromEnvironment(configuration, PROPERTY_AZURE_REQUEST_READ_TIMEOUT,
+                Duration.ofSeconds(60), logger).toSeconds();
+    }
+
+    private Duration readIdleTimeout;
+    private Duration writeIdleTimeout;
+    private Duration connectTimeout;
+    private Duration idleTimeout = Duration.ofSeconds(60);
+    private ProxyOptions proxyOptions;
+    private Configuration configuration;
+    private WebClientOptions webClientOptions;
+    private final Vertx vertx;
+
+    /**
+     * Creates VertxAsyncHttpClientBuilder.
+     *
+     * @param vertx The {@link Vertx} instance to pass to the {@link WebClient}.
+     */
+    public VertxHttpClientBuilder(Vertx vertx) {
+        Objects.requireNonNull(vertx, "vertx cannot be null");
+        this.vertx = vertx;
+    }
+
+    /**
+     * Sets the read idle timeout.
+     *
+     * The default read idle timeout is 60 seconds.
+     *
+     * @param  readIdleTimeout the read idle timeout
+     * @return                 the updated VertxAsyncHttpClientBuilder object
+     */
+    public VertxHttpClientBuilder readIdleTimeout(Duration readIdleTimeout) {
+        this.readIdleTimeout = readIdleTimeout;
+        return this;
+    }
+
+    /**
+     * Sets the write idle timeout.
+     *
+     * The default read idle timeout is 60 seconds.
+     *
+     * @param  writeIdleTimeout the write idle timeout
+     * @return                  the updated VertxAsyncHttpClientBuilder object
+     */
+    public VertxHttpClientBuilder writeIdleTimeout(Duration writeIdleTimeout) {
+        this.writeIdleTimeout = writeIdleTimeout;
+        return this;
+    }
+
+    /**
+     * Sets the connect timeout.
+     *
+     * The default connect timeout is 10 seconds.
+     *
+     * @param  connectTimeout the connection timeout
+     * @return                the updated VertxAsyncHttpClientBuilder object
+     */
+    public VertxHttpClientBuilder connectTimeout(Duration connectTimeout) {
+        this.connectTimeout = connectTimeout;
+        return this;
+    }
+
+    /**
+     * Sets the connection idle timeout.
+     *
+     * The default connect timeout is 60 seconds.
+     *
+     * @param  idleTimeout the connection idle timeout
+     * @return             the updated VertxAsyncHttpClientBuilder object
+     */
+    public VertxHttpClientBuilder idleTimeout(Duration idleTimeout) {
+        this.idleTimeout = idleTimeout;
+        return this;
+    }
+
+    /**
+     * Sets proxy configuration.
+     *
+     * @param  proxyOptions The proxy configuration to use.
+     * @return              The updated VertxAsyncHttpClientBuilder object.
+     */
+    public VertxHttpClientBuilder proxy(ProxyOptions proxyOptions) {
+        this.proxyOptions = proxyOptions;
+        return this;
+    }
+
+    /**
+     * Sets the configuration store that is used during construction of the HTTP client.
+     * <p>
+     * The default configuration store is a clone of the {@link Configuration#getGlobalConfiguration() global
+     * configuration store}, use {@link Configuration#NONE} to bypass using configuration settings during construction.
+     *
+     * @param  configuration The configuration store.
+     * @return               The updated VertxAsyncHttpClientBuilder object.
+     */
+    public VertxHttpClientBuilder configuration(Configuration configuration) {
+        this.configuration = configuration;
+        return this;
+    }
+
+    /**
+     * Sets custom {@link WebClientOptions} for the constructed {@link WebClient}.
+     *
+     * @param  webClientOptions The options of the web client.
+     * @return                  The updated VertxAsyncHttpClientBuilder object
+     */
+    public VertxHttpClientBuilder webClientOptions(WebClientOptions webClientOptions) {
+        this.webClientOptions = webClientOptions;
+        return this;
+    }
+
+    /**
+     * Creates a new Vert.x {@link com.azure.core.http.HttpClient} instance on every call, using the
+     * configuration set in the builder at the time of the build method call.
+     *
+     * @return A new Vert.x backed {@link com.azure.core.http.HttpClient} instance.
+     */
+    public HttpClient build() {
+        if (this.webClientOptions == null) {
+            this.webClientOptions = new WebClientOptions();
+        }
+
+        if (this.connectTimeout != null) {
+            this.webClientOptions.setConnectTimeout((int) this.connectTimeout.toMillis());
+        } else {
+            this.webClientOptions.setConnectTimeout((int) DEFAULT_CONNECT_TIMEOUT);
+        }
+
+        if (this.readIdleTimeout != null) {
+            this.webClientOptions.setReadIdleTimeout((int) this.readIdleTimeout.toSeconds());
+        } else {
+            this.webClientOptions.setReadIdleTimeout((int) DEFAULT_READ_TIMEOUT);
+        }
+
+        if (this.writeIdleTimeout != null) {
+            this.webClientOptions.setWriteIdleTimeout((int) this.writeIdleTimeout.toSeconds());
+        } else {
+            this.webClientOptions.setWriteIdleTimeout((int) DEFAULT_WRITE_TIMEOUT);
+        }
+
+        this.webClientOptions.setIdleTimeout((int) this.idleTimeout.toSeconds());
+
+        Configuration buildConfiguration = (configuration == null)
+                ? Configuration.getGlobalConfiguration()
+                : configuration;
+
+        ProxyOptions buildProxyOptions = (this.proxyOptions == null && buildConfiguration != Configuration.NONE)
+                ? ProxyOptions.fromConfiguration(buildConfiguration, true)
+                : this.proxyOptions;
+
+        if (buildProxyOptions != null) {
+            io.vertx.core.net.ProxyOptions vertxProxyOptions = new io.vertx.core.net.ProxyOptions();
+            InetSocketAddress proxyAddress = buildProxyOptions.getAddress();
+
+            if (proxyAddress != null) {
+                vertxProxyOptions.setHost(proxyAddress.getHostName());
+                vertxProxyOptions.setPort(proxyAddress.getPort());
+            }
+
+            String proxyUsername = buildProxyOptions.getUsername();
+            String proxyPassword = buildProxyOptions.getPassword();
+            if (proxyUsername != null && proxyPassword != null) {
+                vertxProxyOptions.setUsername(proxyUsername);
+                vertxProxyOptions.setPassword(proxyPassword);
+            }
+
+            ProxyOptions.Type type = buildProxyOptions.getType();
+            if (type != null) {
+                try {
+                    ProxyType proxyType = ProxyType.valueOf(type.name());
+                    vertxProxyOptions.setType(proxyType);
+                } catch (IllegalArgumentException e) {
+                    throw new IllegalStateException("Unknown Vert.x proxy type: " + type.name(), e);
+                }
+            }
+
+            String nonProxyHostsString = proxyOptions.getNonProxyHosts();
+            if (nonProxyHostsString != null) {
+                //  Undo Azure ProxyOptions string sanitization since Vert.x has its own logic
+                List<String> nonProxyHosts = Arrays.asList(nonProxyHostsString.split("\\|"))
+                        .stream()
+                        .map(host -> host.replaceAll("\\\\E", "")
+                                .replaceAll("\\\\Q", "")
+                                .replaceAll("\\.\\.", ""))
+                        .collect(Collectors.toList());
+                webClientOptions.setNonProxyHosts(nonProxyHosts);
+            }
+
+            webClientOptions.setProxyOptions(vertxProxyOptions);
+        }
+
+        WebClient client = WebClient.create(this.vertx, this.webClientOptions);
+        return new VertxHttpClient(client, this.webClientOptions);
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientProvider.java b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientProvider.java
new file mode 100644
index 0000000..73120d3
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpClientProvider.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.util.Set;
+
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.CDI;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpClientProvider;
+import com.azure.core.util.HttpClientOptions;
+import io.vertx.core.Vertx;
+import io.vertx.ext.web.client.WebClient;
+
+/**
+ * {@link HttpClientProvider} backed by the Vert.x {@link WebClient}
+ */
+public class VertxHttpClientProvider implements HttpClientProvider {
+
+    @Override
+    public HttpClient createInstance() {
+        return createInstance(null);
+    }
+
+    @Override
+    public HttpClient createInstance(HttpClientOptions clientOptions) {
+        VertxHttpClientBuilder builder = new VertxHttpClientBuilder(getVertx());
+        if (clientOptions != null) {
+            builder = builder.proxy(clientOptions.getProxyOptions())
+                    .configuration(clientOptions.getConfiguration())
+                    .connectTimeout(clientOptions.getConnectTimeout())
+                    .idleTimeout(clientOptions.getConnectionIdleTimeout())
+                    .writeIdleTimeout(clientOptions.getWriteTimeout())
+                    .readIdleTimeout(clientOptions.getReadTimeout());
+        }
+        return builder.build();
+    }
+
+    /**
+     * Obtains a reference to the Quarkus managed {@link Vertx} instance
+     * 
+     * @return The Quarkus managed {@link Vertx} instance
+     */
+    private static final Vertx getVertx() {
+        BeanManager beanManager = CDI.current().getBeanManager();
+        Set<Bean<?>> beans = beanManager.getBeans(Vertx.class);
+        if (beans.isEmpty()) {
+            throw new IllegalStateException("Failed to discover Vert.x bean from the CDI bean manager");
+        }
+
+        if (beans.size() > 1) {
+            throw new IllegalStateException(
+                    "Expected 1 Vert.x bean in the CDI bean manager but " + beans.size() + " were found");
+        }
+
+        Bean<?> bean = beanManager.resolve(beans);
+        Object reference = beanManager.getReference(bean, Vertx.class, beanManager.createCreationalContext(bean));
+        return Vertx.class.cast(reference);
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpRequest.java b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpRequest.java
new file mode 100644
index 0000000..e6f9e60
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpRequest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import io.vertx.core.buffer.Buffer;
+import io.vertx.ext.web.client.HttpRequest;
+
+/**
+ * Holds a Vert.x {@link HttpRequest} together with a body payload.
+ */
+class VertxHttpRequest {
+    private final Buffer body;
+    private final HttpRequest<Buffer> delegate;
+
+    public VertxHttpRequest(HttpRequest<Buffer> delegate, Buffer body) {
+        this.delegate = delegate;
+        this.body = body;
+    }
+
+    public void send(VertxHttpResponseHandler handler) {
+        delegate.sendBuffer(body, handler);
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpResponse.java b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpResponse.java
new file mode 100644
index 0000000..7d71964
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpResponse.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import java.nio.charset.Charset;
+
+import com.azure.core.http.HttpHeaders;
+import com.azure.core.http.HttpRequest;
+import com.azure.core.http.HttpResponse;
+import com.azure.core.util.CoreUtils;
+import io.vertx.core.MultiMap;
+import reactor.core.publisher.Mono;
+
+abstract class VertxHttpResponse extends HttpResponse {
+
+    private final io.vertx.ext.web.client.HttpResponse response;
+    private final HttpHeaders headers;
+
+    VertxHttpResponse(HttpRequest request, io.vertx.ext.web.client.HttpResponse response) {
+        super(request);
+        this.response = response;
+        this.headers = fromVertxHttpHeaders(response.headers());
+    }
+
+    private HttpHeaders fromVertxHttpHeaders(MultiMap headers) {
+        HttpHeaders azureHeaders = new HttpHeaders();
+        headers.names().forEach(name -> azureHeaders.set(name, headers.getAll(name)));
+        return azureHeaders;
+    }
+
+    protected io.vertx.ext.web.client.HttpResponse getVertxHttpResponse() {
+        return this.response;
+    }
+
+    @Override
+    public int getStatusCode() {
+        return response.statusCode();
+    }
+
+    @Override
+    public String getHeaderValue(String name) {
+        return this.headers.getValue(name);
+    }
+
+    @Override
+    public HttpHeaders getHeaders() {
+        return this.headers;
+    }
+
+    @Override
+    public final Mono<String> getBodyAsString() {
+        return getBodyAsByteArray().map(bytes -> CoreUtils.bomAwareToString(bytes, getHeaderValue("Content-Type")));
+    }
+
+    @Override
+    public final Mono<String> getBodyAsString(Charset charset) {
+        return Mono.fromCallable(() -> this.response.bodyAsString(charset.toString()));
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpResponseHandler.java b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpResponseHandler.java
new file mode 100644
index 0000000..9e33e0b
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/runtime/src/main/java/org/apache/camel/quarkus/support/azure/core/http/vertx/VertxHttpResponseHandler.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.support.azure.core.http.vertx;
+
+import com.azure.core.http.HttpRequest;
+import io.vertx.core.AsyncResult;
+import io.vertx.core.Handler;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.ext.web.client.HttpResponse;
+import reactor.core.publisher.MonoSink;
+
+/**
+ * {@link Handler} for Azure HTTP responses.
+ */
+class VertxHttpResponseHandler implements Handler<AsyncResult<HttpResponse<Buffer>>> {
+
+    private final HttpRequest request;
+    private final MonoSink<com.azure.core.http.HttpResponse> sink;
+    private final boolean eagerlyReadResponse;
+
+    VertxHttpResponseHandler(HttpRequest request, MonoSink<com.azure.core.http.HttpResponse> sink,
+            boolean eagerlyReadResponse) {
+        this.request = request;
+        this.sink = sink;
+        this.eagerlyReadResponse = eagerlyReadResponse;
+    }
+
+    @Override
+    public void handle(AsyncResult<HttpResponse<Buffer>> event) {
+        if (event.succeeded()) {
+            VertxHttpResponse response;
+            if (eagerlyReadResponse) {
+                io.vertx.ext.web.client.HttpResponse<Buffer> originalResponse = event.result();
+                response = new BufferedVertxHttpResponse(request, originalResponse, originalResponse.body());
+            } else {
+                response = new VertxHttpAsyncResponse(request, event.result());
+            }
+            sink.success(response);
+        } else {
+            if (event.cause() != null) {
+                sink.error(event.cause());
+            }
+        }
+    }
+}
diff --git a/extensions-support/azure-core-http-client-vertx/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions-support/azure-core-http-client-vertx/runtime/src/main/resources/META-INF/quarkus-extension.yaml
new file mode 100644
index 0000000..5f875c0
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+---
+name: "Camel Quarkus Support Azure Core HTTP Client Vert.x"
+description: "Camel Quarkus Support Azure Core HTTP Client Vert.x"
+metadata:
+  unlisted: true
+  keywords:
+    - "camel"
+  guide: "https://quarkus.io/guides/camel"
+  categories:
+    - "integration"
\ No newline at end of file
diff --git a/extensions-support/azure-core-http-client-vertx/runtime/src/main/resources/META-INF/services/com.azure.core.http.HttpClientProvider b/extensions-support/azure-core-http-client-vertx/runtime/src/main/resources/META-INF/services/com.azure.core.http.HttpClientProvider
new file mode 100644
index 0000000..8487b59
--- /dev/null
+++ b/extensions-support/azure-core-http-client-vertx/runtime/src/main/resources/META-INF/services/com.azure.core.http.HttpClientProvider
@@ -0,0 +1 @@
+org.apache.camel.quarkus.support.azure.core.http.vertx.VertxHttpClientProvider
\ No newline at end of file
diff --git a/extensions-support/azure-core/deployment/pom.xml b/extensions-support/azure-core/deployment/pom.xml
index 91a5018..b762e0a 100644
--- a/extensions-support/azure-core/deployment/pom.xml
+++ b/extensions-support/azure-core/deployment/pom.xml
@@ -35,12 +35,12 @@
             <artifactId>quarkus-core-deployment</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-jackson-dataformat-xml-deployment</artifactId>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-netty-deployment</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-reactor-netty-deployment</artifactId>
+            <artifactId>camel-quarkus-support-jackson-dataformat-xml-deployment</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
diff --git a/extensions-support/azure-core/runtime/pom.xml b/extensions-support/azure-core/runtime/pom.xml
index 701cd25..0319e50 100644
--- a/extensions-support/azure-core/runtime/pom.xml
+++ b/extensions-support/azure-core/runtime/pom.xml
@@ -52,16 +52,22 @@
             <artifactId>quarkus-core</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-jackson-dataformat-xml</artifactId>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-netty</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-reactor-netty</artifactId>
+            <artifactId>camel-quarkus-support-jackson-dataformat-xml</artifactId>
         </dependency>
         <dependency>
             <groupId>com.azure</groupId>
             <artifactId>azure-core</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.azure</groupId>
+                    <artifactId>azure-core-http-netty</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
     </dependencies>
 
diff --git a/extensions-support/pom.xml b/extensions-support/pom.xml
index 4a8cad3..5e6b35e 100644
--- a/extensions-support/pom.xml
+++ b/extensions-support/pom.xml
@@ -38,6 +38,7 @@
         <module>aws</module>
         <module>aws2</module>
         <module>azure-core</module>
+        <module>azure-core-http-client-vertx</module>
         <module>bouncycastle</module>
         <module>commons-logging</module>
         <module>consul-client</module>
diff --git a/extensions/azure-eventhubs/runtime/pom.xml b/extensions/azure-eventhubs/runtime/pom.xml
index 3c79b20..5be7c8b 100644
--- a/extensions/azure-eventhubs/runtime/pom.xml
+++ b/extensions/azure-eventhubs/runtime/pom.xml
@@ -59,6 +59,12 @@
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-azure-eventhubs</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.azure</groupId>
+                    <artifactId>azure-core-http-netty</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
     </dependencies>
 
diff --git a/extensions/azure-storage-blob/deployment/pom.xml b/extensions/azure-storage-blob/deployment/pom.xml
index 49ff729..e341501 100644
--- a/extensions/azure-storage-blob/deployment/pom.xml
+++ b/extensions/azure-storage-blob/deployment/pom.xml
@@ -36,7 +36,7 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-azure-core-deployment</artifactId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx-deployment</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
diff --git a/extensions/azure-storage-blob/runtime/pom.xml b/extensions/azure-storage-blob/runtime/pom.xml
index d432e32..3e59347 100644
--- a/extensions/azure-storage-blob/runtime/pom.xml
+++ b/extensions/azure-storage-blob/runtime/pom.xml
@@ -54,11 +54,17 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-azure-core</artifactId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-azure-storage-blob</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.azure</groupId>
+                    <artifactId>azure-core-http-netty</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
     </dependencies>
 
diff --git a/extensions/azure-storage-queue/deployment/pom.xml b/extensions/azure-storage-queue/deployment/pom.xml
index 6819a3e..e6b3473 100644
--- a/extensions/azure-storage-queue/deployment/pom.xml
+++ b/extensions/azure-storage-queue/deployment/pom.xml
@@ -36,7 +36,7 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-azure-core-deployment</artifactId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx-deployment</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
diff --git a/extensions/azure-storage-queue/runtime/pom.xml b/extensions/azure-storage-queue/runtime/pom.xml
index ecb18ff..4afc269 100644
--- a/extensions/azure-storage-queue/runtime/pom.xml
+++ b/extensions/azure-storage-queue/runtime/pom.xml
@@ -54,11 +54,17 @@
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
-            <artifactId>camel-quarkus-support-azure-core</artifactId>
+            <artifactId>camel-quarkus-support-azure-core-http-client-vertx</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-azure-storage-queue</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.azure</groupId>
+                    <artifactId>azure-core-http-netty</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
     </dependencies>
 
diff --git a/integration-test-groups/azure/azure-storage-blob/src/test/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobTest.java b/integration-test-groups/azure/azure-storage-blob/src/test/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobTest.java
index 6594824..7a3e8c1 100644
--- a/integration-test-groups/azure/azure-storage-blob/src/test/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobTest.java
+++ b/integration-test-groups/azure/azure-storage-blob/src/test/java/org/apache/camel/quarkus/component/azure/storage/blob/it/AzureStorageBlobTest.java
@@ -27,13 +27,7 @@ import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
-import com.azure.core.http.policy.HttpLogDetailLevel;
-import com.azure.core.http.policy.HttpLogOptions;
-import com.azure.storage.blob.BlobContainerClient;
-import com.azure.storage.blob.BlobServiceClient;
-import com.azure.storage.blob.BlobServiceClientBuilder;
 import com.azure.storage.blob.models.BlockListType;
-import com.azure.storage.common.StorageSharedKeyCredential;
 import io.quarkus.test.common.QuarkusTestResource;
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
@@ -65,31 +59,26 @@ class AzureStorageBlobTest {
 
     @BeforeAll
     static void beforeAll() {
-        getClient().create();
+        final Config config = ConfigProvider.getConfig();
+        String containerName = config.getValue("azure.blob.container.name", String.class);
+        int port = config.getValue("quarkus.http.test-port", int.class);
+        RestAssured.port = port;
+        RestAssured.given()
+                .queryParam("containerName", containerName)
+                .post("/azure-storage-blob/blob/container")
+                .then()
+                .statusCode(201);
     }
 
     @AfterAll
     static void afterAll() {
-        getClient().delete();
-    }
-
-    private static BlobContainerClient getClient() {
         final Config config = ConfigProvider.getConfig();
-        final String azureStorageAccountName = config.getValue("azure.storage.account-name",
-                String.class);
-        final String azureStorageAccountKey = config
-                .getValue("azure.storage.account-key", String.class);
-
-        StorageSharedKeyCredential credentials = new StorageSharedKeyCredential(azureStorageAccountName,
-                azureStorageAccountKey);
-        BlobServiceClient client = new BlobServiceClientBuilder()
-                .endpoint(config.getValue("azure.blob.service.url", String.class))
-                .credential(credentials)
-                .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS).setPrettyPrintBody(true))
-                .buildClient();
-
         String containerName = config.getValue("azure.blob.container.name", String.class);
-        return client.getBlobContainerClient(containerName);
+        RestAssured.given()
+                .queryParam("containerName", containerName)
+                .delete("/azure-storage-blob/blob/container")
+                .then()
+                .statusCode(204);
     }
 
     @Test
diff --git a/pom.xml b/pom.xml
index 5cbdeea..5c3b1f8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,8 @@
         <awssdk.version>2.17.127</awssdk.version><!-- @sync io.quarkiverse.amazonservices:quarkus-amazon-services-parent:${quarkiverse-amazonservices.version} prop:awssdk.version -->
         <aws-java-sdk.version>1.11.714</aws-java-sdk.version>
         <azure-sdk-bom.version>1.0.5</azure-sdk-bom.version><!-- Keep in sync with camel-azure component versions -->
+        <azure-core.version>1.21.0</azure-core.version><!-- @sync com.azure:azure-sdk-bom:${azure-sdk-bom.version} dep:com.azure:azure-core -->
+        <azure-core-test.version>1.7.3</azure-core-test.version>
         <bouncycastle.version>1.70</bouncycastle.version><!-- @sync io.quarkus:quarkus-bom:${quarkus.version} dep:org.bouncycastle:bcprov-jdk15on -->
         <commons-beanutils.version>${commons-beanutils-version}</commons-beanutils.version>
         <commons-cli.version>1.4</commons-cli.version><!-- keep in sync with Quarkus, via quarkus-bootstrap-core -->
diff --git a/poms/bom-test/pom.xml b/poms/bom-test/pom.xml
index fced647..53b1e1c 100644
--- a/poms/bom-test/pom.xml
+++ b/poms/bom-test/pom.xml
@@ -301,6 +301,26 @@
                 <artifactId>aws-java-sdk-core</artifactId>
                 <version>${aws-java-sdk.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.azure</groupId>
+                <artifactId>azure-core</artifactId>
+                <version>${azure-core.version}</version>
+                <type>test-jar</type>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>com.azure</groupId>
+                <artifactId>azure-core-test</artifactId>
+                <version>${azure-core-test.version}</version>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>com.azure</groupId>
+                <artifactId>azure-core-test</artifactId>
+                <version>${azure-core-test.version}</version>
+                <type>test-jar</type>
+                <scope>test</scope>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/poms/bom/pom.xml b/poms/bom/pom.xml
index 2218c60..564e4a2 100644
--- a/poms/bom/pom.xml
+++ b/poms/bom/pom.xml
@@ -5556,6 +5556,16 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-support-azure-core-http-client-vertx</artifactId>
+                <version>${camel-quarkus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-support-azure-core-http-client-vertx-deployment</artifactId>
+                <version>${camel-quarkus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
                 <artifactId>camel-quarkus-support-bouncycastle</artifactId>
                 <version>${camel-quarkus.version}</version>
             </dependency>