diff --git a/camel-k-main/camel-k-runtime-health/pom.xml b/camel-k-main/camel-k-runtime-health/pom.xml
index b02262375..5149dc290 100644
--- a/camel-k-main/camel-k-runtime-health/pom.xml
+++ b/camel-k-main/camel-k-runtime-health/pom.xml
@@ -45,7 +45,7 @@
org.apache.camel.k
- camel-k-runtime-inspector
+ camel-k-runtime-http
diff --git a/camel-k-main/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthContextCustomizer.java b/camel-k-main/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthContextCustomizer.java
index 8d70f1049..f1308d2b2 100644
--- a/camel-k-main/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthContextCustomizer.java
+++ b/camel-k-main/camel-k-runtime-health/src/main/java/org/apache/camel/k/health/HealthContextCustomizer.java
@@ -23,6 +23,8 @@
import io.vertx.core.json.Json;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
+import io.vertx.ext.web.Route;
+import io.vertx.ext.web.Router;
import org.apache.camel.CamelContext;
import org.apache.camel.Ordered;
import org.apache.camel.health.HealthCheck;
@@ -33,7 +35,7 @@
import org.apache.camel.impl.health.ContextHealthCheck;
import org.apache.camel.impl.health.RoutesHealthCheckRepository;
import org.apache.camel.k.ContextCustomizer;
-import org.apache.camel.k.inspector.InspectorCustomizer;
+import org.apache.camel.k.http.PlatformHttpRouter;
public class HealthContextCustomizer implements ContextCustomizer {
public static final String DEFAULT_PATH = "/health";
@@ -83,7 +85,7 @@ public void setIncludeContext(boolean includeContext) {
@Override
public int getOrder() {
- return Ordered.HIGHEST;
+ return Ordered.LOWEST;
}
@Override
@@ -105,14 +107,15 @@ public void apply(CamelContext camelContext) {
throw new RuntimeException(e);
}
- camelContext.getRegistry().bind(
- "health-route",
- customizer(camelContext)
+ // add health route
+ addRoute(
+ camelContext,
+ PlatformHttpRouter.lookup(camelContext).get()
);
}
- private InspectorCustomizer customizer(CamelContext camelContext) {
- return router -> router.route(HttpMethod.GET, path).handler(routingContext -> {
+ private Route addRoute(CamelContext camelContext, Router router) {
+ return router.route(HttpMethod.GET, path).handler(routingContext -> {
int code = 200;
Collection results = HealthCheckHelper.invoke(
diff --git a/camel-k-main/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthCustomizerTest.java b/camel-k-main/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthCustomizerTest.java
index 1a7fb069a..caf512e2e 100644
--- a/camel-k-main/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthCustomizerTest.java
+++ b/camel-k-main/camel-k-runtime-health/src/test/java/org/apache/camel/k/health/HealthCustomizerTest.java
@@ -21,7 +21,7 @@
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.k.Runtime;
-import org.apache.camel.k.inspector.InspectorContextCustomizer;
+import org.apache.camel.k.http.PlatformHttpServiceContextCustomizer;
import org.apache.camel.test.AvailablePortFinder;
import org.apache.camel.util.ObjectHelper;
import org.junit.jupiter.params.ParameterizedTest;
@@ -46,22 +46,22 @@ public void configure() throws Exception {
}
});
- HealthContextCustomizer healthCustomizer = new HealthContextCustomizer();
- healthCustomizer.apply(runtime.getCamelContext());
-
- InspectorContextCustomizer inspectorCustomizer = new InspectorContextCustomizer();
- inspectorCustomizer.setBindPort(AvailablePortFinder.getNextAvailable());
+ PlatformHttpServiceContextCustomizer phsc = new PlatformHttpServiceContextCustomizer();
+ phsc.setBindPort(AvailablePortFinder.getNextAvailable());
String url;
if (ObjectHelper.isEmpty(path)) {
- url = "http://localhost:" + inspectorCustomizer.getBindPort() + HealthContextCustomizer.DEFAULT_PATH;
+ url = "http://localhost:" + phsc.getBindPort() + HealthContextCustomizer.DEFAULT_PATH;
} else {
- inspectorCustomizer.setPath(path);
+ phsc.setPath(path);
- url = "http://localhost:" + inspectorCustomizer.getBindPort() + path + HealthContextCustomizer.DEFAULT_PATH;
+ url = "http://localhost:" + phsc.getBindPort() + path + HealthContextCustomizer.DEFAULT_PATH;
}
- inspectorCustomizer.apply(runtime.getCamelContext());
+ phsc.apply(runtime.getCamelContext());
+
+ HealthContextCustomizer healthCustomizer = new HealthContextCustomizer();
+ healthCustomizer.apply(runtime.getCamelContext());
try {
runtime.getCamelContext().start();
diff --git a/camel-k-main/camel-k-runtime-inspector/pom.xml b/camel-k-main/camel-k-runtime-http/pom.xml
similarity index 96%
rename from camel-k-main/camel-k-runtime-inspector/pom.xml
rename to camel-k-main/camel-k-runtime-http/pom.xml
index 2915644ef..97db7863a 100644
--- a/camel-k-main/camel-k-runtime-inspector/pom.xml
+++ b/camel-k-main/camel-k-runtime-http/pom.xml
@@ -25,7 +25,7 @@
4.0.0
- camel-k-runtime-inspector
+ camel-k-runtime-http
@@ -39,6 +39,10 @@
org.apache.camel
camel-core-engine
+
+ org.apache.camel
+ camel-platform-http
+
org.apache.camel.k
camel-k-runtime-core
diff --git a/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpRouter.java b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpRouter.java
new file mode 100644
index 000000000..5f33f2fff
--- /dev/null
+++ b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpRouter.java
@@ -0,0 +1,50 @@
+/*
+ * 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.k.http;
+
+import io.vertx.ext.web.Router;
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.platform.http.PlatformHttpConstants;
+import org.apache.camel.support.CamelContextHelper;
+
+public class PlatformHttpRouter {
+ public static final String PLATFORM_HTTP_ROUTER_NAME = PlatformHttpConstants.PLATFORM_HTTP_COMPONENT_NAME + "-router";
+
+ private final Router router;
+
+ public PlatformHttpRouter(Router router) {
+ this.router = router;
+ }
+
+ public Router get() {
+ return router;
+ }
+
+ // **********************
+ //
+ // Helpers
+ //
+ // **********************
+
+ public static PlatformHttpRouter lookup(CamelContext camelContext) {
+ return CamelContextHelper.mandatoryLookup(
+ camelContext,
+ PlatformHttpRouter.PLATFORM_HTTP_ROUTER_NAME,
+ PlatformHttpRouter.class
+ );
+ }
+}
diff --git a/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServer.java b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServer.java
new file mode 100644
index 000000000..6d1bd7de1
--- /dev/null
+++ b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServer.java
@@ -0,0 +1,178 @@
+/*
+ * 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.k.http;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+
+import io.vertx.core.Handler;
+import io.vertx.core.Vertx;
+import io.vertx.core.http.HttpServer;
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.RoutingContext;
+import io.vertx.ext.web.handler.BodyHandler;
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.platform.http.PlatformHttpConstants;
+import org.apache.camel.support.service.ServiceSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class PlatformHttpServer extends ServiceSupport {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PlatformHttpServer.class);
+
+ private final CamelContext context;
+ private final PlatformHttpServiceConfiguration configuration;
+ private final Vertx vertx;
+ private final ExecutorService executor;
+
+ private HttpServer server;
+
+ public PlatformHttpServer(CamelContext context, PlatformHttpServiceConfiguration configuration, Vertx vertx, ExecutorService executor) {
+ this.context = context;
+ this.configuration = configuration;
+ this.vertx = vertx;
+ this.executor = executor;
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ startAsync().toCompletableFuture().join();
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ try {
+ if (server != null) {
+ stopAsync().toCompletableFuture().join();
+ }
+ } finally {
+ this.server = null;
+ }
+ }
+
+ private CompletionStage startAsync() {
+ final Router router = Router.router(vertx);
+ final Router subRouter = Router.router(vertx);
+
+ router.route()
+ .order(Integer.MIN_VALUE)
+ .handler(ctx -> {
+ ctx.request().resume();
+ createBodyHandler().handle(ctx);
+ });
+
+ router.mountSubRouter(configuration.getPath(), subRouter);
+
+ context.getRegistry().bind(PlatformHttpRouter.PLATFORM_HTTP_ROUTER_NAME, new PlatformHttpRouter(subRouter));
+
+ //HttpServerOptions options = new HttpServerOptions();
+ if (configuration.getSslContextParameters() != null) {
+ // TODO: add ssl support
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ server = vertx.createHttpServer();
+
+ return CompletableFuture.runAsync(
+ () -> {
+ CountDownLatch latch = new CountDownLatch(1);
+ server.requestHandler(router).listen(configuration.getBindPort(), configuration.getBindHost(), result -> {
+ try {
+ if (result.failed()) {
+ LOGGER.warn("Failed to start Vert.x HttpServer on {}:{}, reason: {}",
+ configuration.getBindHost(),
+ configuration.getBindPort(),
+ result.cause().getMessage()
+ );
+
+ throw new RuntimeException(result.cause());
+ }
+
+ LOGGER.info("Vert.x HttpServer started on {}:{}", configuration.getBindHost(), configuration.getBindPort());
+ } finally {
+ latch.countDown();
+ }
+ });
+
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ },
+ executor
+ );
+ }
+
+ protected CompletionStage stopAsync() {
+ return CompletableFuture.runAsync(
+ () -> {
+ CountDownLatch latch = new CountDownLatch(1);
+
+ // remove the platform-http component
+ context.removeComponent(PlatformHttpConstants.PLATFORM_HTTP_COMPONENT_NAME);
+
+ server.close(result -> {
+ try {
+ if (result.failed()) {
+ LOGGER.warn("Failed to close Vert.x HttpServer reason: {}",
+ result.cause().getMessage()
+ );
+
+ throw new RuntimeException(result.cause());
+ }
+
+ LOGGER.info("Vert.x HttpServer stopped");
+ } finally {
+ latch.countDown();
+ }
+ });
+
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ },
+ executor
+ );
+ }
+
+ private Handler createBodyHandler() {
+ BodyHandler bodyHandler = BodyHandler.create();
+
+ if (configuration.getMaxBodySize() != null) {
+ bodyHandler.setBodyLimit(configuration.getMaxBodySize().longValueExact());
+ }
+
+ bodyHandler.setHandleFileUploads(configuration.getBodyHandler().isHandleFileUploads());
+ bodyHandler.setUploadsDirectory(configuration.getBodyHandler().getUploadsDirectory());
+ bodyHandler.setDeleteUploadedFilesOnEnd(configuration.getBodyHandler().isDeleteUploadedFilesOnEnd());
+ bodyHandler.setMergeFormAttributes(configuration.getBodyHandler().isMergeFormAttributes());
+ bodyHandler.setPreallocateBodyBuffer(configuration.getBodyHandler().isPreallocateBodyBuffer());
+
+ return new Handler() {
+ @Override
+ public void handle(RoutingContext event) {
+ event.request().resume();
+ bodyHandler.handle(event);
+ }
+ };
+ }
+}
diff --git a/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServiceConfiguration.java b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServiceConfiguration.java
new file mode 100644
index 000000000..659ecab8d
--- /dev/null
+++ b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServiceConfiguration.java
@@ -0,0 +1,131 @@
+/*
+ * 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.k.http;
+
+import java.math.BigInteger;
+
+import org.apache.camel.support.jsse.SSLContextParameters;
+
+public class PlatformHttpServiceConfiguration {
+ public static final String DEFAULT_BIND_HOST = "0.0.0.0";
+ public static final int DEFAULT_BIND_PORT = 8081;
+ public static final String DEFAULT_PATH = "/";
+
+ private String bindHost = DEFAULT_BIND_HOST;
+ private int bindPort = DEFAULT_BIND_PORT;
+ private String path = DEFAULT_PATH;
+ private BigInteger maxBodySize;
+
+ private BodyHandler bodyHandler = new BodyHandler();
+ private SSLContextParameters sslContextParameters;
+
+ public String getBindHost() {
+ return bindHost;
+ }
+
+ public void setBindHost(String bindHost) {
+ this.bindHost = bindHost;
+ }
+
+ public int getBindPort() {
+ return bindPort;
+ }
+
+ public void setBindPort(int bindPort) {
+ this.bindPort = bindPort;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public BigInteger getMaxBodySize() {
+ return maxBodySize;
+ }
+
+ public void setMaxBodySize(BigInteger maxBodySize) {
+ this.maxBodySize = maxBodySize;
+ }
+
+ public BodyHandler getBodyHandler() {
+ return bodyHandler;
+ }
+
+ public void setBodyHandler(BodyHandler bodyHandler) {
+ this.bodyHandler = bodyHandler;
+ }
+
+ public SSLContextParameters getSslContextParameters() {
+ return sslContextParameters;
+ }
+
+ public void setSslContextParameters(SSLContextParameters sslContextParameters) {
+ this.sslContextParameters = sslContextParameters;
+ }
+
+ public static class BodyHandler {
+ private boolean handleFileUploads = true;
+ private String uploadsDirectory = "file-uploads";
+ private boolean mergeFormAttributes = true;
+ private boolean deleteUploadedFilesOnEnd;
+ private boolean preallocateBodyBuffer = true;
+
+ public boolean isHandleFileUploads() {
+ return handleFileUploads;
+ }
+
+ public void setHandleFileUploads(boolean handleFileUploads) {
+ this.handleFileUploads = handleFileUploads;
+ }
+
+ public String getUploadsDirectory() {
+ return uploadsDirectory;
+ }
+
+ public void setUploadsDirectory(String uploadsDirectory) {
+ this.uploadsDirectory = uploadsDirectory;
+ }
+
+ public boolean isMergeFormAttributes() {
+ return mergeFormAttributes;
+ }
+
+ public void setMergeFormAttributes(boolean mergeFormAttributes) {
+ this.mergeFormAttributes = mergeFormAttributes;
+ }
+
+ public boolean isDeleteUploadedFilesOnEnd() {
+ return deleteUploadedFilesOnEnd;
+ }
+
+ public void setDeleteUploadedFilesOnEnd(boolean deleteUploadedFilesOnEnd) {
+ this.deleteUploadedFilesOnEnd = deleteUploadedFilesOnEnd;
+ }
+
+ public boolean isPreallocateBodyBuffer() {
+ return preallocateBodyBuffer;
+ }
+
+ public void setPreallocateBodyBuffer(boolean preallocateBodyBuffer) {
+ this.preallocateBodyBuffer = preallocateBodyBuffer;
+ }
+ }
+}
diff --git a/camel-k-main/camel-k-runtime-inspector/src/main/java/org/apache/camel/k/inspector/InspectorContextCustomizer.java b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServiceContextCustomizer.java
similarity index 52%
rename from camel-k-main/camel-k-runtime-inspector/src/main/java/org/apache/camel/k/inspector/InspectorContextCustomizer.java
rename to camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServiceContextCustomizer.java
index 5bcc396d6..cc100ae70 100644
--- a/camel-k-main/camel-k-runtime-inspector/src/main/java/org/apache/camel/k/inspector/InspectorContextCustomizer.java
+++ b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServiceContextCustomizer.java
@@ -14,65 +14,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.camel.k.inspector;
+package org.apache.camel.k.http;
import org.apache.camel.CamelContext;
import org.apache.camel.Ordered;
+import org.apache.camel.component.platform.http.PlatformHttpComponent;
+import org.apache.camel.component.platform.http.PlatformHttpConstants;
import org.apache.camel.k.ContextCustomizer;
+import org.apache.camel.k.http.engine.RuntimePlatformHttpEngine;
-public class InspectorContextCustomizer implements ContextCustomizer {
- public static final String DEFAULT_BIND_HOST = "0.0.0.0";
- public static final int DEFAULT_BIND_PORT = 8081;
- public static final String DEFAULT_PATH = "/";
-
- private String bindHost;
- private int bindPort;
- private String path;
- private InspectorEndpoint endpoint;
-
- public InspectorContextCustomizer() {
- this.bindHost = DEFAULT_BIND_HOST;
- this.bindPort = DEFAULT_BIND_PORT;
- this.path = DEFAULT_PATH;
- }
-
- public String getBindHost() {
- return bindHost;
- }
-
- public void setBindHost(String bindHost) {
- this.bindHost = bindHost;
- }
-
- public int getBindPort() {
- return bindPort;
- }
-
- public void setBindPort(int bindPort) {
- this.bindPort = bindPort;
- }
-
- public String getPath() {
- return path;
- }
-
- public void setPath(String path) {
- this.path = path;
- }
+public class PlatformHttpServiceContextCustomizer extends PlatformHttpServiceConfiguration implements ContextCustomizer {
+ private PlatformHttpServiceEndpoint endpoint;
@Override
public int getOrder() {
- return Ordered.LOWEST;
+ return Ordered.HIGHEST;
}
@Override
public void apply(CamelContext camelContext) {
- endpoint = new InspectorEndpoint(camelContext, bindHost, bindPort, path);
+ endpoint = new PlatformHttpServiceEndpoint(camelContext, this);
try {
camelContext.addService(endpoint, true, true);
} catch (Exception e) {
throw new RuntimeException(e);
}
+
+ // add the platform-http component
+ PlatformHttpComponent component = new PlatformHttpComponent();
+ component.setEngine(new RuntimePlatformHttpEngine());
+
+ camelContext.addComponent(PlatformHttpConstants.PLATFORM_HTTP_COMPONENT_NAME, component);
}
}
diff --git a/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServiceEndpoint.java b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServiceEndpoint.java
new file mode 100644
index 000000000..1f904e9d6
--- /dev/null
+++ b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/PlatformHttpServiceEndpoint.java
@@ -0,0 +1,118 @@
+/*
+ * 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.k.http;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import org.apache.camel.CamelContext;
+import org.apache.camel.support.CamelContextHelper;
+import org.apache.camel.support.service.ServiceSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PlatformHttpServiceEndpoint extends ServiceSupport {
+ private static final Logger LOGGER = LoggerFactory.getLogger(PlatformHttpServiceEndpoint.class);
+
+ private final CamelContext context;
+ private final PlatformHttpServiceConfiguration configuration;
+
+ private Vertx vertx;
+ private boolean localVertx;
+ private PlatformHttpServer vertxHttpServer;
+ private ExecutorService executor;
+
+ public PlatformHttpServiceEndpoint(CamelContext context, PlatformHttpServiceConfiguration configuration) {
+ this.context = context;
+ this.configuration = configuration;
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ vertx = CamelContextHelper.findByType(context, Vertx.class);
+ executor = context.getExecutorServiceManager().newSingleThreadExecutor(this, "platform-http-service");
+
+ if (vertx != null) {
+ LOGGER.info("Found Vert.x instance in registry: {}", vertx);
+ } else {
+ VertxOptions options = CamelContextHelper.findByType(context, VertxOptions.class);
+ if (options == null) {
+ options = new VertxOptions();
+ }
+
+ LOGGER.info("Creating new Vert.x instance");
+
+ vertx = Vertx.vertx(options);
+ localVertx = true;
+ }
+
+ vertxHttpServer = new PlatformHttpServer(context, configuration, vertx, executor);
+ vertxHttpServer.start();
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ if (vertxHttpServer != null) {
+ vertxHttpServer.stop();
+ }
+
+ if (vertx != null && localVertx) {
+ Future> future = executor.submit(
+ () -> {
+ CountDownLatch latch = new CountDownLatch(1);
+
+ vertx.close(result -> {
+ try {
+ if (result.failed()) {
+ LOGGER.warn("Failed to close Vert.x reason: {}",
+ result.cause().getMessage()
+ );
+
+ throw new RuntimeException(result.cause());
+ }
+
+ LOGGER.info("Vert.x stopped");
+ } finally {
+ latch.countDown();
+ }
+ });
+
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ );
+
+ try {
+ future.get();
+ } finally {
+ vertx = null;
+ localVertx = false;
+ }
+ }
+
+ if (executor != null) {
+ context.getExecutorServiceManager().shutdown(executor);
+ executor = null;
+ }
+ }
+}
diff --git a/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/engine/RuntimePlatformHttpConsumer.java b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/engine/RuntimePlatformHttpConsumer.java
new file mode 100644
index 000000000..e438c3235
--- /dev/null
+++ b/camel-k-main/camel-k-runtime-http/src/main/java/org/apache/camel/k/http/engine/RuntimePlatformHttpConsumer.java
@@ -0,0 +1,389 @@
+/*
+ * 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.k.http.engine;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import io.vertx.core.MultiMap;
+import io.vertx.core.buffer.Buffer;
+import io.vertx.core.http.HttpMethod;
+import io.vertx.core.http.HttpServerRequest;
+import io.vertx.core.http.HttpServerResponse;
+import io.vertx.ext.web.Route;
+import io.vertx.ext.web.RoutingContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.NoTypeConversionAvailableException;
+import org.apache.camel.Processor;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.component.platform.http.PlatformHttpEndpoint;
+import org.apache.camel.component.platform.http.spi.Method;
+import org.apache.camel.k.http.PlatformHttpRouter;
+import org.apache.camel.spi.HeaderFilterStrategy;
+import org.apache.camel.support.DefaultConsumer;
+import org.apache.camel.support.DefaultMessage;
+import org.apache.camel.support.ExchangeHelper;
+import org.apache.camel.support.MessageHelper;
+import org.apache.camel.support.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RuntimePlatformHttpConsumer extends DefaultConsumer {
+ private static final Logger LOG = LoggerFactory.getLogger(RuntimePlatformHttpConsumer.class);
+ private static final Pattern PATH_PARAMETER_PATTERN = Pattern.compile("\\{([^/}]+)\\}");
+
+ private Route route;
+
+ public RuntimePlatformHttpConsumer(PlatformHttpEndpoint endpoint, Processor processor) {
+ super(endpoint, processor);
+ }
+
+ @Override
+ public PlatformHttpEndpoint getEndpoint() {
+ return (PlatformHttpEndpoint) super.getEndpoint();
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+
+ final PlatformHttpEndpoint endpoint = getEndpoint();
+ final PlatformHttpRouter router = PlatformHttpRouter.lookup(endpoint.getCamelContext());
+ final String path = endpoint.getPath();
+ final String vertxPathParamPath = PATH_PARAMETER_PATTERN.matcher(path).replaceAll(":$1");
+ final Route newRoute = router.get().route(vertxPathParamPath);
+
+ final Set methods = Method.parseList(endpoint.getHttpMethodRestrict());
+ if (!methods.equals(Method.getAll())) {
+ methods.stream().forEach(m -> newRoute.method(HttpMethod.valueOf(m.name())));
+ }
+ if (endpoint.getConsumes() != null) {
+ newRoute.consumes(endpoint.getConsumes());
+ }
+ if (endpoint.getProduces() != null) {
+ newRoute.produces(endpoint.getProduces());
+ }
+
+ newRoute.handler(
+ ctx -> {
+ Exchange exchg = null;
+ try {
+ final Exchange exchange = exchg = toExchange(ctx);
+ createUoW(exchange);
+ getAsyncProcessor().process(
+ exchange,
+ doneSync -> writeResponse(ctx, exchange, getEndpoint().getHeaderFilterStrategy()));
+ } catch (Exception e) {
+ ctx.fail(e);
+ getExceptionHandler().handleException("Failed handling platform-http endpoint " + path, exchg, e);
+ } finally {
+ if (exchg != null) {
+ doneUoW(exchg);
+ }
+ }
+ });
+
+ this.route = newRoute;
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ if (route != null) {
+ route.remove();
+ route = null;
+ }
+ super.doStop();
+ }
+
+ @Override
+ protected void doSuspend() throws Exception {
+ if (route != null) {
+ route.disable();
+ }
+ super.doSuspend();
+ }
+
+ @Override
+ protected void doResume() throws Exception {
+ if (route != null) {
+ route.enable();
+ }
+ super.doResume();
+ }
+
+ static Object toHttpResponse(HttpServerResponse response, Message message, HeaderFilterStrategy headerFilterStrategy) {
+ final Exchange exchange = message.getExchange();
+ final TypeConverter tc = exchange.getContext().getTypeConverter();
+ final int code = determineResponseCode(exchange, message.getBody());
+
+ response.setStatusCode(code);
+
+ // copy headers from Message to Response
+ if (headerFilterStrategy != null) {
+ for (Map.Entry entry : message.getHeaders().entrySet()) {
+ final String key = entry.getKey();
+ final Object value = entry.getValue();
+ // use an iterator as there can be multiple values. (must not use a delimiter)
+ final Iterator> it = ObjectHelper.createIterator(value, null);
+
+ String firstValue = null;
+ List values = null;
+
+ while (it.hasNext()) {
+ final String headerValue = tc.convertTo(String.class, it.next());
+ if (headerValue != null
+ && !headerFilterStrategy.applyFilterToCamelHeaders(key, headerValue, exchange)) {
+ if (firstValue == null) {
+ firstValue = headerValue;
+ } else {
+ if (values == null) {
+ values = new ArrayList<>();
+ values.add(firstValue);
+ }
+ values.add(headerValue);
+ }
+ }
+ }
+ if (values != null) {
+ response.putHeader(key, values);
+ } else if (firstValue != null) {
+ response.putHeader(key, firstValue);
+ }
+ }
+ }
+
+ Object body = message.getBody();
+ final Exception exception = exchange.getException();
+
+ if (exception != null) {
+ // we failed due an exception so print it as plain text
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw);
+
+ exception.printStackTrace(pw);
+
+ // the body should then be the stacktrace
+ body = ByteBuffer.wrap(sw.toString().getBytes(StandardCharsets.UTF_8));
+ // force content type to be text/plain as that is what the stacktrace is
+ message.setHeader(Exchange.CONTENT_TYPE, "text/plain; charset=utf-8");
+
+ // and mark the exception as failure handled, as we handled it by returning it as the response
+ ExchangeHelper.setFailureHandled(exchange);
+ }
+
+ // set the content type in the response.
+ final String contentType = MessageHelper.getContentType(message);
+ if (contentType != null) {
+ // set content-type
+ response.putHeader("Content-Type", contentType);
+ }
+ return body;
+ }
+
+ /*
+ * Copied from org.apache.camel.http.common.DefaultHttpBinding.determineResponseCode(Exchange, Object)
+ * If DefaultHttpBinding.determineResponseCode(Exchange, Object) is moved to a module without the servlet-api
+ * dependency we could eventually consume it from there.
+ */
+ static int determineResponseCode(Exchange camelExchange, Object body) {
+ boolean failed = camelExchange.isFailed();
+ int defaultCode = failed ? 500 : 200;
+
+ Message message = camelExchange.getMessage();
+ Integer currentCode = message.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
+ int codeToUse = currentCode == null ? defaultCode : currentCode;
+
+ if (codeToUse != 500) {
+ if ((body == null) || (body instanceof String && ((String) body).trim().isEmpty())) {
+ // no content
+ codeToUse = currentCode == null ? 204 : currentCode;
+ }
+ }
+
+ return codeToUse;
+ }
+
+ static void writeResponse(RoutingContext ctx, Exchange camelExchange, HeaderFilterStrategy headerFilterStrategy) {
+ final Object body = toHttpResponse(ctx.response(), camelExchange.getMessage(), headerFilterStrategy);
+
+ final HttpServerResponse response = ctx.response();
+ if (body == null) {
+ LOG.trace("No payload to send as reply for exchange: {}", camelExchange);
+ response.end();
+ } else if (body instanceof String) {
+ response.end((String) body);
+ } else if (body instanceof InputStream) {
+ final byte[] bytes = new byte[4096];
+ try (InputStream in = (InputStream) body) {
+ int len;
+ while ((len = in.read(bytes)) >= 0) {
+ response.write(Buffer.buffer(len).appendBytes(bytes, 0, len));
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ response.end();
+ } else {
+ final TypeConverter tc = camelExchange.getContext().getTypeConverter();
+ try {
+ final ByteBuffer bb = tc.mandatoryConvertTo(ByteBuffer.class, body);
+ response.end(Buffer.buffer(bb.capacity()).setBytes(0, bb));
+ } catch (TypeConversionException | NoTypeConversionAvailableException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ }
+
+ private Exchange toExchange(RoutingContext ctx) {
+ final Exchange exchange = getEndpoint().createExchange();
+ Message in = toCamelMessage(ctx, exchange);
+
+ final String charset = ctx.parsedHeaders().contentType().parameter("charset");
+ if (charset != null) {
+ exchange.setProperty(Exchange.CHARSET_NAME, charset);
+ in.setHeader(Exchange.HTTP_CHARACTER_ENCODING, charset);
+ }
+
+ exchange.setIn(in);
+ return exchange;
+ }
+
+ private Message toCamelMessage(RoutingContext ctx, Exchange exchange) {
+ final Message result = new DefaultMessage(exchange);
+
+ final HeaderFilterStrategy headerFilterStrategy = getEndpoint().getHeaderFilterStrategy();
+ populateCamelHeaders(ctx, result.getHeaders(), exchange, headerFilterStrategy);
+ final String mimeType = ctx.parsedHeaders().contentType().value();
+ final boolean isMultipartFormData = "multipart/form-data".equals(mimeType);
+ if ("application/x-www-form-urlencoded".equals(mimeType) || isMultipartFormData) {
+ final MultiMap formData = ctx.request().formAttributes();
+ final Map body = new HashMap<>();
+ for (String key : formData.names()) {
+ for (String value : formData.getAll(key)) {
+ if (headerFilterStrategy != null
+ && !headerFilterStrategy.applyFilterToExternalHeaders(key, value, exchange)) {
+ appendHeader(result.getHeaders(), key, value);
+ appendHeader(body, key, value);
+ }
+ }
+ }
+ result.setBody(body);
+ if (isMultipartFormData) {
+ //populateAttachments(ctx.fileUploads(), result);
+ }
+ } else {
+ // extract body by myself if undertow parser didn't handle and the method is allowed to have one
+ // body is extracted as byte[] then auto TypeConverter kicks in
+ Method m = Method.valueOf(ctx.request().method().name());
+ if (m.canHaveBody()) {
+ final Buffer body = ctx.getBody();
+ if (body != null) {
+ result.setBody(body.getBytes());
+ }
+ } else {
+ result.setBody(null);
+ }
+ }
+ return result;
+ }
+
+ static void populateCamelHeaders(
+ RoutingContext ctx,
+ Map headersMap,
+ Exchange exchange,
+ HeaderFilterStrategy headerFilterStrategy) {
+
+ final HttpServerRequest request = ctx.request();
+ headersMap.put(Exchange.HTTP_PATH, request.path());
+
+ if (headerFilterStrategy != null) {
+ final MultiMap requestHeaders = request.headers();
+ final String authz = requestHeaders.get("authorization");
+ // store a special header that this request was authenticated using HTTP Basic
+ if (authz != null && authz.trim().startsWith("Basic")) {
+ if (!headerFilterStrategy.applyFilterToExternalHeaders(Exchange.AUTHENTICATION, "Basic", exchange)) {
+ appendHeader(headersMap, Exchange.AUTHENTICATION, "Basic");
+ }
+ }
+ for (String name : requestHeaders.names()) {
+ // add the headers one by one, and use the header filter strategy
+ for (String value : requestHeaders.getAll(name)) {
+ if (!headerFilterStrategy.applyFilterToExternalHeaders(name.toString(), value, exchange)) {
+ appendHeader(headersMap, name.toString(), value);
+ }
+ }
+ }
+
+ // process uri parameters as headers
+ final MultiMap pathParameters = ctx.queryParams();
+ // continue if the map is not empty, otherwise there are no params
+ if (!pathParameters.isEmpty()) {
+ for (String name : pathParameters.names()) {
+ for (String value : pathParameters.getAll(name)) {
+ if (!headerFilterStrategy.applyFilterToExternalHeaders(name, value, exchange)) {
+ appendHeader(headersMap, name, value);
+ }
+ }
+ }
+ }
+ }
+
+ // Path parameters
+ ctx.pathParams().forEach((k, v) -> appendHeader(headersMap, k, v));
+
+ // NOTE: these headers is applied using the same logic as camel-http/camel-jetty to be consistent
+ headersMap.put(Exchange.HTTP_METHOD, request.method().toString());
+ // strip query parameters from the uri
+ headersMap.put(Exchange.HTTP_URL, request.absoluteURI());
+ // uri is without the host and port
+ headersMap.put(Exchange.HTTP_URI, request.uri());
+ headersMap.put(Exchange.HTTP_QUERY, request.query());
+ headersMap.put(Exchange.HTTP_RAW_QUERY, request.query());
+ }
+
+ @SuppressWarnings("unchecked")
+ static void appendHeader(Map headers, String key, Object value) {
+ if (headers.containsKey(key)) {
+ Object existing = headers.get(key);
+ List
org.apache.camel.k
- camel-k-runtime-inspector
+ camel-k-runtime-http
${project.version}
diff --git a/examples/camel-k-runtime-example-health/README.adoc b/examples/camel-k-runtime-example-health/README.adoc
deleted file mode 100644
index 1c19469c6..000000000
--- a/examples/camel-k-runtime-example-health/README.adoc
+++ /dev/null
@@ -1,25 +0,0 @@
-Health Apache Camel K Runtime example
-======================================
-
-This repository contains an Apache Camel-K Runtime application that expose `/health` endpoint to gather Camel context status.
-
-In order to run it:
-```bash
-mvn clean exec:java
-```
-while it is running (from another terminal) you can access the rest camel route exposed through the servlet with:
-```bash
-curl http://localhost:8082/health
-```
-if the camel context has started properly that should get:
-```json
-{
- "checks": [
- {
- "name": "route:my-route",
- "status": "UP"
- }
- ],
- "status": "UP"
-}
-```
\ No newline at end of file
diff --git a/examples/camel-k-runtime-example-rest/README.adoc b/examples/camel-k-runtime-example-rest/README.adoc
new file mode 100644
index 000000000..bc2024f2c
--- /dev/null
+++ b/examples/camel-k-runtime-example-rest/README.adoc
@@ -0,0 +1,58 @@
+Rest Apache Camel K Runtime example
+======================================
+
+This repository contains an Apache Camel-K Runtime application that expose a `rest` endpoint and and `/health` endpoint to gather Camel context status.
+
+In order to run it:
+[code,shell]
+----
+mvn clean exec:java
+----
+
+while it is running (from another terminal) you can access to:
+
+* health info with:
++
+[code,shell]
+----
+http http://localhost:8080/health
+----
++
+if the camel context has started properly that should get:
++
+[code,json]
+----
+{
+ "checks": [
+ {
+ "name": "context",
+ "status": "UP"
+ },
+ {
+ "name": "route:route1",
+ "status": "UP"
+ },
+ {
+ "name": "route:route2",
+ "status": "UP"
+ }
+ ],
+ "status": "UP"
+}
+----
+
+* rest endpoint info with:
++
+[code,shell]
+----
+http POST http://localhost:8080/rest a=b
+----
++
+if the route has started properly that should get:
++
+[code,json]
+----
+{
+ "A": "B"
+}
+----
\ No newline at end of file
diff --git a/examples/camel-k-runtime-example-health/src/main/resources/application.properties b/examples/camel-k-runtime-example-rest/data/application.properties
similarity index 93%
rename from examples/camel-k-runtime-example-health/src/main/resources/application.properties
rename to examples/camel-k-runtime-example-rest/data/application.properties
index cf08a8322..3977fbf92 100644
--- a/examples/camel-k-runtime-example-health/src/main/resources/application.properties
+++ b/examples/camel-k-runtime-example-rest/data/application.properties
@@ -30,6 +30,6 @@ camel.main.stream-caching-spool-directory = ${java.io.tmpdir}/camel-k
#
# Camel K
#
-customizer.inspector.enabled = true
-customizer.inspector.bind-port = 8082
+customizer.platform-http.enabled = true
+customizer.platform-http.bind-port = 8080
customizer.health.enabled = true
\ No newline at end of file
diff --git a/examples/camel-k-runtime-example-health/src/main/resources/routes.groovy b/examples/camel-k-runtime-example-rest/data/routes.groovy
similarity index 78%
rename from examples/camel-k-runtime-example-health/src/main/resources/routes.groovy
rename to examples/camel-k-runtime-example-rest/data/routes.groovy
index a1818bd12..28a8fadc0 100644
--- a/examples/camel-k-runtime-example-health/src/main/resources/routes.groovy
+++ b/examples/camel-k-runtime-example-rest/data/routes.groovy
@@ -15,7 +15,16 @@
* limitations under the License.
*/
-from('netty-http:http:0.0.0.0:8080//test')
- .routeId('my-route')
- .convertBodyTo(String.class)
- .to('log:info')
\ No newline at end of file
+rest {
+ configuration {
+ component 'platform-http'
+ }
+
+ post('/rest') {
+ to 'direct:post'
+ }
+}
+
+from('direct:post')
+ .transform().body(String.class, b -> b.toUpperCase())
+ .to('log:post')
\ No newline at end of file
diff --git a/examples/camel-k-runtime-example-health/pom.xml b/examples/camel-k-runtime-example-rest/pom.xml
similarity index 84%
rename from examples/camel-k-runtime-example-health/pom.xml
rename to examples/camel-k-runtime-example-rest/pom.xml
index ea2f08d25..57da37696 100644
--- a/examples/camel-k-runtime-example-health/pom.xml
+++ b/examples/camel-k-runtime-example-rest/pom.xml
@@ -25,7 +25,7 @@
4.0.0
- camel-k-runtime-example-health
+ camel-k-runtime-example-rest
@@ -41,13 +41,21 @@
camel-k-runtime-health
- org.apache.camel
- camel-netty-http
+ org.apache.camel.k
+ camel-k-runtime-http
org.apache.camel
camel-log
+
+ org.apache.camel
+ camel-rest
+
+
+ org.apache.camel
+ camel-direct
+
@@ -70,11 +78,11 @@
camel.k.conf
- ${project.basedir}/src/main/resources/application.properties
+ ${project.basedir}/data/application.properties
camel.k.routes
- file:${project.basedir}/src/main/resources/routes.groovy
+ file:${project.basedir}/data/routes.groovy
diff --git a/examples/pom.xml b/examples/pom.xml
index cc3357b75..e4e1e2e37 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -33,7 +33,7 @@
- camel-k-runtime-example-health
+ camel-k-runtime-example-rest
camel-k-runtime-example-groovy
camel-k-runtime-example-yaml
camel-k-runtime-example-knative
diff --git a/pom.xml b/pom.xml
index b42c7c1d4..926d79c77 100644
--- a/pom.xml
+++ b/pom.xml
@@ -318,7 +318,7 @@
org.apache.camel.k
- camel-k-runtime-inspector
+ camel-k-runtime-http
${project.version}
diff --git a/tooling/camel-k-maven-plugin/src/it/generate-catalog-main/verify.groovy b/tooling/camel-k-maven-plugin/src/it/generate-catalog-main/verify.groovy
index bd8666d00..bc588911a 100644
--- a/tooling/camel-k-maven-plugin/src/it/generate-catalog-main/verify.groovy
+++ b/tooling/camel-k-maven-plugin/src/it/generate-catalog-main/verify.groovy
@@ -26,8 +26,8 @@ assert catalog.spec.runtime.capabilities['health'].dependencies[0].groupId == 'o
assert catalog.spec.runtime.capabilities['health'].dependencies[0].artifactId == 'camel-k-runtime-health'
assert catalog.spec.runtime.capabilities['rest'].dependencies[0].groupId == 'org.apache.camel'
assert catalog.spec.runtime.capabilities['rest'].dependencies[0].artifactId == 'camel-rest'
-assert catalog.spec.runtime.capabilities['rest'].dependencies[1].groupId == 'org.apache.camel'
-assert catalog.spec.runtime.capabilities['rest'].dependencies[1].artifactId == 'camel-undertow'
+assert catalog.spec.runtime.capabilities['rest'].dependencies[1].groupId == 'org.apache.camel.k'
+assert catalog.spec.runtime.capabilities['rest'].dependencies[1].artifactId == 'camel-k-runtime-http'
assert catalog.metadata.labels['camel.apache.org/runtime.version'] == runtimeVersion
diff --git a/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/GenerateCatalogMojo.java b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/GenerateCatalogMojo.java
index c3e53414f..b1637a25f 100644
--- a/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/GenerateCatalogMojo.java
+++ b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/GenerateCatalogMojo.java
@@ -133,7 +133,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
"rest",
new CamelCapability.Builder()
.addDependency("org.apache.camel", "camel-rest")
- .addDependency("org.apache.camel", "camel-undertow")
+ .addDependency("org.apache.camel.k", "camel-k-runtime-http")
.build());
break;
case "quarkus":
diff --git a/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3x.java b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3x.java
index e23544368..60ed03c86 100644
--- a/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3x.java
+++ b/tooling/camel-k-maven-plugin/src/main/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3x.java
@@ -132,7 +132,7 @@ public void process(MavenProject project, CamelCatalog catalog, CamelCatalogSpec
specBuilder.putArtifact(
new CamelArtifact.Builder()
.groupId("org.apache.camel.k")
- .artifactId("camel-k-runtime-inspector")
+ .artifactId("camel-k-runtime-http")
.build()
);
specBuilder.putArtifact(
diff --git a/tooling/camel-k-maven-plugin/src/test/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3Test.java b/tooling/camel-k-maven-plugin/src/test/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3Test.java
index 9a953bcc9..4496d427b 100644
--- a/tooling/camel-k-maven-plugin/src/test/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3Test.java
+++ b/tooling/camel-k-maven-plugin/src/test/java/org/apache/camel/k/tooling/maven/processors/CatalogProcessor3Test.java
@@ -80,7 +80,7 @@ public void testArtifactsEnrichment() {
Map artifactMap = spec.getArtifacts();
assertThat(artifactMap).containsKeys("camel-k-runtime-health");
- assertThat(artifactMap).containsKeys("camel-k-runtime-inspector");
+ assertThat(artifactMap).containsKeys("camel-k-runtime-http");
assertThat(artifactMap).containsKeys("camel-k-runtime-webhook");
assertThat(artifactMap.get("camel-k-runtime-knative")).satisfies(a -> {