This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch man in repository https://gitbox.apache.org/repos/asf/camel.git
commit 8fc7653ceda00f14eb7228b25305ea73aaf6b026 Author: Claus Ibsen <[email protected]> AuthorDate: Tue Jul 29 16:01:37 2025 +0200 CAMEL-22285: platform-http-main - Dev consoles should be registered as management endpoints --- .../http/main/DefaultMainHttpServerFactory.java | 19 +- .../platform/http/main/MainHttpServer.java | 2 + .../platform/http/main/ManagementHttpServer.java | 254 +++++++++++++++++++++ .../http/main/MainHttpFakeHealthCheck.java | 2 +- .../http/main/MainHttpServerRouteTest.java | 1 - ...rverTest.java => ManagementHttpServerTest.java} | 5 +- ...entServerConfigurationPropertiesConfigurer.java | 21 ++ .../camel-main-configuration-metadata.json | 5 +- core/camel-main/src/main/docs/main.adoc | 7 +- .../org/apache/camel/main/BaseMainSupport.java | 12 +- ...ttpManagementServerConfigurationProperties.java | 74 +++++- 11 files changed, 372 insertions(+), 30 deletions(-) diff --git a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/DefaultMainHttpServerFactory.java b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/DefaultMainHttpServerFactory.java index faf85922e4f..0ae2a43f927 100644 --- a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/DefaultMainHttpServerFactory.java +++ b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/DefaultMainHttpServerFactory.java @@ -67,20 +67,9 @@ public class DefaultMainHttpServerFactory implements CamelContextAware, MainHttp dir = TempDirHelper.resolveTempDir(camelContext, null, dir); server.setFileUploadDirectory(dir); } - server.setInfoEnabled(configuration.isInfoEnabled()); server.setStaticEnabled(configuration.isStaticEnabled()); server.setStaticContextPath(configuration.getStaticContextPath()); server.setStaticSourceDir(configuration.getStaticSourceDir()); - server.setDevConsoleEnabled(configuration.isDevConsoleEnabled()); - server.setHealthCheckEnabled(configuration.isHealthCheckEnabled()); - server.setHealthPath(configuration.getHealthPath()); - server.setJolokiaEnabled(configuration.isJolokiaEnabled()); - server.setJolokiaPath(configuration.getJolokiaPath()); - server.setMetricsEnabled(configuration.isMetricsEnabled()); - server.setUploadEnabled(configuration.isUploadEnabled()); - server.setUploadSourceDir(configuration.getUploadSourceDir()); - server.setDownloadEnabled(configuration.isDownloadEnabled()); - server.setSendEnabled(configuration.isSendEnabled()); if (configuration.isAuthenticationEnabled()) { configureAuthentication(server, configuration); @@ -98,9 +87,7 @@ public class DefaultMainHttpServerFactory implements CamelContextAware, MainHttp server.setHost(configuration.getHost()); server.setPort(configuration.getPort()); server.setPath(configuration.getPath()); - if (configuration.getMaxBodySize() != null) { - server.setMaxBodySize(configuration.getMaxBodySize()); - } + server.setUseGlobalSslContextParameters(configuration.isUseGlobalSslContextParameters()); server.setInfoEnabled(configuration.isInfoEnabled()); server.setDevConsoleEnabled(configuration.isDevConsoleEnabled()); @@ -109,6 +96,10 @@ public class DefaultMainHttpServerFactory implements CamelContextAware, MainHttp server.setJolokiaEnabled(configuration.isJolokiaEnabled()); server.setJolokiaPath(configuration.getJolokiaPath()); server.setMetricsEnabled(configuration.isMetricsEnabled()); + server.setUploadEnabled(configuration.isUploadEnabled()); + server.setUploadSourceDir(configuration.getUploadSourceDir()); + server.setDownloadEnabled(configuration.isDownloadEnabled()); + server.setSendEnabled(configuration.isSendEnabled()); if (configuration.isAuthenticationEnabled()) { configureAuthentication(server, configuration); diff --git a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java index d05de720fc9..e18de965004 100644 --- a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java +++ b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/MainHttpServer.java @@ -38,6 +38,7 @@ import org.apache.camel.component.platform.http.vertx.VertxPlatformHttpServer; import org.apache.camel.component.platform.http.vertx.VertxPlatformHttpServerConfiguration; import org.apache.camel.support.ResolverHelper; import org.apache.camel.support.jsse.SSLContextParameters; +import org.apache.camel.support.service.ServiceHelper; import org.apache.camel.support.service.ServiceSupport; import org.apache.camel.util.FileUtil; import org.apache.camel.util.IOHelper; @@ -214,6 +215,7 @@ public class MainHttpServer extends ServiceSupport implements CamelContextAware, @Override protected void doStart() throws Exception { ObjectHelper.notNull(camelContext, "CamelContext"); + ServiceHelper.startService(server); String routerName = VertxPlatformHttpRouter.getRouterNameFromPort(getPort()); router = VertxPlatformHttpRouter.lookup(camelContext, routerName); platformHttpComponent = camelContext.getComponent("platform-http", PlatformHttpComponent.class); diff --git a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java index 9b873b7f6d1..a4dc1104dbd 100644 --- a/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java +++ b/components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/ManagementHttpServer.java @@ -16,6 +16,9 @@ */ package org.apache.camel.component.platform.http.main; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.util.ArrayList; @@ -28,12 +31,14 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.StringJoiner; import java.util.TreeSet; import java.util.regex.Pattern; import java.util.stream.Collectors; import io.vertx.core.Handler; import io.vertx.core.http.HttpMethod; +import io.vertx.ext.web.RequestBody; import io.vertx.ext.web.Route; import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.BodyHandler; @@ -64,15 +69,23 @@ import org.apache.camel.health.HealthCheckHelper; import org.apache.camel.health.HealthCheckRegistry; import org.apache.camel.http.base.HttpProtocolHeaderFilterStrategy; import org.apache.camel.spi.HeaderFilterStrategy; +import org.apache.camel.spi.PackageScanResourceResolver; import org.apache.camel.spi.ReloadStrategy; +import org.apache.camel.spi.Resource; +import org.apache.camel.spi.ResourceLoader; import org.apache.camel.support.CamelContextHelper; import org.apache.camel.support.EndpointHelper; import org.apache.camel.support.ExceptionHelper; +import org.apache.camel.support.LoggerHelper; import org.apache.camel.support.MessageHelper; +import org.apache.camel.support.PluginHelper; import org.apache.camel.support.ResolverHelper; import org.apache.camel.support.jsse.SSLContextParameters; import org.apache.camel.support.service.ServiceHelper; import org.apache.camel.support.service.ServiceSupport; +import org.apache.camel.util.AntPathMatcher; +import org.apache.camel.util.FileUtil; +import org.apache.camel.util.IOHelper; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.StopWatch; import org.apache.camel.util.StringHelper; @@ -110,6 +123,9 @@ public class ManagementHttpServer extends ServiceSupport implements CamelContext private boolean metricsEnabled; private String healthPath; private String jolokiaPath; + private boolean uploadEnabled; + private String uploadSourceDir; + private boolean downloadEnabled; private boolean sendEnabled; @Override @@ -282,6 +298,42 @@ public class ManagementHttpServer extends ServiceSupport implements CamelContext configuration.setUseGlobalSslContextParameters(useGlobalSslContextParameters); } + @ManagedAttribute(description = "Whether file upload is enabled (only for development) (q/upload)") + public boolean isUploadEnabled() { + return uploadEnabled; + } + + /** + * Whether file upload is enabled (only for development) (q/upload) + */ + public void setUploadEnabled(boolean uploadEnabled) { + this.uploadEnabled = uploadEnabled; + } + + @ManagedAttribute(description = "Directory for upload.") + public String getUploadSourceDir() { + return uploadSourceDir; + } + + /** + * Directory for upload. + */ + public void setUploadSourceDir(String uploadSourceDir) { + this.uploadSourceDir = uploadSourceDir; + } + + @ManagedAttribute(description = "Whether file download is enabled (q/download)") + public boolean isDownloadEnabled() { + return downloadEnabled; + } + + /** + * Whether file download is enabled (q/download) + */ + public void setDownloadEnabled(boolean downloadEnabled) { + this.downloadEnabled = downloadEnabled; + } + @ManagedAttribute(description = "Whether send message is enabled (q/send)") public boolean isSendEnabled() { return sendEnabled; @@ -379,6 +431,15 @@ public class ManagementHttpServer extends ServiceSupport implements CamelContext if (jolokiaEnabled) { setupJolokia(); } + if (uploadEnabled) { + if (uploadSourceDir == null) { + throw new IllegalArgumentException("UploadSourceDir must be configured when uploadEnabled=true"); + } + setupUploadConsole(uploadSourceDir); + } + if (downloadEnabled) { + setupDownloadConsole(); + } if (sendEnabled) { setupSendConsole(); } @@ -597,6 +658,199 @@ public class ManagementHttpServer extends ServiceSupport implements CamelContext "text/plain,application/json", null); } + protected void setupUploadConsole(final String dir) { + final Route upload = router.route("/q/upload/:filename") + .method(HttpMethod.PUT) + // need body handler to handle file uploads + .handler(BodyHandler.create(true)); + + final Route uploadDelete = router.route("/q/upload/:filename"); + uploadDelete.method(HttpMethod.DELETE); + + Handler<RoutingContext> handler = new Handler<RoutingContext>() { + @Override + public void handle(RoutingContext ctx) { + String name = ctx.pathParam("filename"); + if (name == null) { + ctx.response().setStatusCode(400); + ctx.end(); + return; + } + + int status = 200; + boolean delete = HttpMethod.DELETE == ctx.request().method(); + if (delete) { + if (name.contains("*")) { + if (name.equals("*")) { + name = "**"; + } + AntPathMatcher match = AntPathMatcher.INSTANCE; + File[] files = new File(dir).listFiles(); + if (files != null) { + for (File f : files) { + if (f.getName().startsWith(".") || f.isHidden()) { + continue; + } + if (match.match(name, f.getName())) { + LOG.info("Deleting file: {}/{}", dir, name); + FileUtil.deleteFile(f); + } + } + } + } else { + File f = new File(dir, name); + if (f.exists() && f.isFile()) { + LOG.info("Deleting file: {}/{}", dir, name); + FileUtil.deleteFile(f); + } + } + } else { + File f = new File(dir, name); + boolean exists = f.isFile() && f.exists(); + LOG.info("{} file: {}/{}", exists ? "Updating" : "Creating", dir, name); + + File tmp = new File(dir, name + ".tmp"); + FileOutputStream fos = null; + try { + fos = new FileOutputStream(tmp, false); + RequestBody rb = ctx.body(); + IOHelper.writeText(rb.asString(), fos); + + FileUtil.renameFileUsingCopy(tmp, f); + FileUtil.deleteFile(tmp); + } catch (Exception e) { + // some kind of error + LOG.warn("Error saving file: {}/{} due to: {}", dir, name, e.getMessage(), e); + status = 500; + } finally { + IOHelper.close(fos); + FileUtil.deleteFile(tmp); + } + } + + ctx.response().setStatusCode(status); + ctx.end(); + } + }; + // use blocking handler as the task can take longer time to complete + upload.handler(new BlockingHandlerDecorator(handler, true)); + uploadDelete.handler(new BlockingHandlerDecorator(handler, true)); + + platformHttpComponent.addHttpManagementEndpoint("/q/upload", "PUT,DELETE", + "multipart/form-data", null, null); + } + + protected void setupDownloadConsole() { + final Route download = router.route("/q/download/*") + .produces("text/plain") + .produces("application/octet-stream") + .method(HttpMethod.GET); + + final AntPathMatcher matcher = AntPathMatcher.INSTANCE; + Handler<RoutingContext> handler = new Handler<RoutingContext>() { + @Override + public void handle(RoutingContext ctx) { + String name = StringHelper.after(ctx.normalizedPath(), "/q/download/"); + boolean cp = "true".equals(ctx.queryParams().get("classpath")); + if (name == null || name.isBlank() || matcher.isPattern(name)) { + Set<String> names = new TreeSet<>(); + if (cp) { + // also look inside classpath + PackageScanResourceResolver resolver = PluginHelper.getPackageScanResourceResolver(camelContext); + resolver.addClassLoader(camelContext.getApplicationContextClassLoader()); + try { + String pattern = "**/*"; + if (name != null && !name.isBlank()) { + pattern = "**/" + name; + } + for (Resource res : resolver.findResources(pattern)) { + String loc = res.getLocation(); + loc = LoggerHelper.sourceNameOnly(loc); + names.add(loc); + } + } catch (Exception e) { + // ignore + } + } + // always include routes + for (org.apache.camel.Route route : camelContext.getRoutes()) { + String loc = route.getSourceLocation(); + if (loc != null) { + loc = LoggerHelper.sourceNameOnly(loc); + if (name == null || name.isBlank() || matcher.match(name, loc)) { + names.add(loc); + } + } + } + + String acp = ctx.request().getHeader("Accept"); + boolean html = acp != null && acp.contains("html"); + StringJoiner sj; + if (html) { + String prefix = StringHelper.after(ctx.normalizedPath(), "/q/download/"); + if (prefix == null) { + prefix = "/q/download/"; + } else { + prefix = ""; + } + ctx.response().putHeader("Content-Type", "text/html"); + sj = new StringJoiner("<br/>"); + for (String n : names) { + sj.add("<a href=" + prefix + n + ">" + n + "</a>"); + } + } else { + ctx.response().putHeader("Content-Type", "text/plain"); + sj = new StringJoiner("\n"); + names.forEach(sj::add); + } + ctx.response().setStatusCode(200); + ctx.end(sj.toString()); + } else { + // load file as resource (try both classpath and file) + ResourceLoader loader = PluginHelper.getResourceLoader(camelContext); + Resource res = loader.resolveResource("classpath:" + name); + if (res == null || !res.exists()) { + // attempt without path + res = loader.resolveResource("classpath:" + FileUtil.stripPath(name)); + } + if (res == null || !res.exists()) { + for (org.apache.camel.Route route : camelContext.getRoutes()) { + String loc = route.getSourceLocation(); + if (loc != null) { + loc = LoggerHelper.sourceNameOnly(loc); + if (matcher.match(name, loc)) { + res = route.getSourceResource(); + break; + } + } + } + } + if (res != null && res.exists()) { + ctx.response().putHeader("Content-Type", "application/octet-stream"); + ctx.response().putHeader("Content-Disposition", + "attachment; filename=\"" + FileUtil.stripPath(name) + "\""); + ctx.response().setStatusCode(200); + String data = null; + try { + data = IOHelper.loadText(res.getInputStream()); + } catch (IOException e) { + // ignore + } + ctx.end(data); + } else { + ctx.response().setStatusCode(204); + ctx.end(); + } + } + } + }; + // use blocking handler as the task can take longer time to complete + download.handler(new BlockingHandlerDecorator(handler, true)); + + platformHttpComponent.addHttpManagementEndpoint("/q/download", "GET", + null, "text/plain,application/octet-stream", null); + } + protected void setupSendConsole() { final Route send = router.route("/q/send/") .produces("application/json") diff --git a/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpFakeHealthCheck.java b/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpFakeHealthCheck.java index 5165c1f0284..e63537c399e 100644 --- a/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpFakeHealthCheck.java +++ b/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpFakeHealthCheck.java @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.camel.component.platform.http.main; import java.util.Map; @@ -23,6 +22,7 @@ import org.apache.camel.health.HealthCheckResultBuilder; import org.apache.camel.impl.health.AbstractHealthCheck; public class MainHttpFakeHealthCheck extends AbstractHealthCheck { + protected MainHttpFakeHealthCheck() { super("camel", "consumer:fake"); } diff --git a/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpServerRouteTest.java b/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpServerRouteTest.java index 640ee0b0278..2998a7b3bca 100644 --- a/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpServerRouteTest.java +++ b/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpServerRouteTest.java @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.camel.component.platform.http.main; import java.net.URI; diff --git a/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpServerTest.java b/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/ManagementHttpServerTest.java similarity index 95% rename from components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpServerTest.java rename to components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/ManagementHttpServerTest.java index 7c5a552079c..46600a4aeae 100644 --- a/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/MainHttpServerTest.java +++ b/components/camel-platform-http-main/src/test/java/org/apache/camel/component/platform/http/main/ManagementHttpServerTest.java @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.camel.component.platform.http.main; import java.io.IOException; @@ -30,7 +29,7 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; -class MainHttpServerTest { +class ManagementHttpServerTest { private CamelContext camelContext; @@ -38,7 +37,7 @@ class MainHttpServerTest { @Test public void statusIsNotSatisfied() throws IOException, InterruptedException { - MainHttpServer server = new MainHttpServer(); + ManagementHttpServer server = new ManagementHttpServer(); camelContext = new DefaultCamelContext(); server.setCamelContext(camelContext); diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/HttpManagementServerConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/HttpManagementServerConfigurationPropertiesConfigurer.java index a2f420a87d2..97418f57cfa 100644 --- a/core/camel-main/src/generated/java/org/apache/camel/main/HttpManagementServerConfigurationPropertiesConfigurer.java +++ b/core/camel-main/src/generated/java/org/apache/camel/main/HttpManagementServerConfigurationPropertiesConfigurer.java @@ -26,6 +26,7 @@ public class HttpManagementServerConfigurationPropertiesConfigurer extends org.a map.put("AuthenticationPath", java.lang.String.class); map.put("BasicPropertiesFile", java.lang.String.class); map.put("DevConsoleEnabled", boolean.class); + map.put("DownloadEnabled", boolean.class); map.put("Enabled", boolean.class); map.put("HealthCheckEnabled", boolean.class); map.put("HealthPath", java.lang.String.class); @@ -40,6 +41,8 @@ public class HttpManagementServerConfigurationPropertiesConfigurer extends org.a map.put("Path", java.lang.String.class); map.put("Port", int.class); map.put("SendEnabled", boolean.class); + map.put("UploadEnabled", boolean.class); + map.put("UploadSourceDir", java.lang.String.class); map.put("UseGlobalSslContextParameters", boolean.class); ALL_OPTIONS = map; } @@ -56,6 +59,8 @@ public class HttpManagementServerConfigurationPropertiesConfigurer extends org.a case "basicPropertiesFile": target.setBasicPropertiesFile(property(camelContext, java.lang.String.class, value)); return true; case "devconsoleenabled": case "devConsoleEnabled": target.setDevConsoleEnabled(property(camelContext, boolean.class, value)); return true; + case "downloadenabled": + case "downloadEnabled": target.setDownloadEnabled(property(camelContext, boolean.class, value)); return true; case "enabled": target.setEnabled(property(camelContext, boolean.class, value)); return true; case "healthcheckenabled": case "healthCheckEnabled": target.setHealthCheckEnabled(property(camelContext, boolean.class, value)); return true; @@ -80,6 +85,10 @@ public class HttpManagementServerConfigurationPropertiesConfigurer extends org.a case "port": target.setPort(property(camelContext, int.class, value)); return true; case "sendenabled": case "sendEnabled": target.setSendEnabled(property(camelContext, boolean.class, value)); return true; + case "uploadenabled": + case "uploadEnabled": target.setUploadEnabled(property(camelContext, boolean.class, value)); return true; + case "uploadsourcedir": + case "uploadSourceDir": target.setUploadSourceDir(property(camelContext, java.lang.String.class, value)); return true; case "useglobalsslcontextparameters": case "useGlobalSslContextParameters": target.setUseGlobalSslContextParameters(property(camelContext, boolean.class, value)); return true; default: return false; @@ -102,6 +111,8 @@ public class HttpManagementServerConfigurationPropertiesConfigurer extends org.a case "basicPropertiesFile": return java.lang.String.class; case "devconsoleenabled": case "devConsoleEnabled": return boolean.class; + case "downloadenabled": + case "downloadEnabled": return boolean.class; case "enabled": return boolean.class; case "healthcheckenabled": case "healthCheckEnabled": return boolean.class; @@ -126,6 +137,10 @@ public class HttpManagementServerConfigurationPropertiesConfigurer extends org.a case "port": return int.class; case "sendenabled": case "sendEnabled": return boolean.class; + case "uploadenabled": + case "uploadEnabled": return boolean.class; + case "uploadsourcedir": + case "uploadSourceDir": return java.lang.String.class; case "useglobalsslcontextparameters": case "useGlobalSslContextParameters": return boolean.class; default: return null; @@ -144,6 +159,8 @@ public class HttpManagementServerConfigurationPropertiesConfigurer extends org.a case "basicPropertiesFile": return target.getBasicPropertiesFile(); case "devconsoleenabled": case "devConsoleEnabled": return target.isDevConsoleEnabled(); + case "downloadenabled": + case "downloadEnabled": return target.isDownloadEnabled(); case "enabled": return target.isEnabled(); case "healthcheckenabled": case "healthCheckEnabled": return target.isHealthCheckEnabled(); @@ -168,6 +185,10 @@ public class HttpManagementServerConfigurationPropertiesConfigurer extends org.a case "port": return target.getPort(); case "sendenabled": case "sendEnabled": return target.isSendEnabled(); + case "uploadenabled": + case "uploadEnabled": return target.isUploadEnabled(); + case "uploadsourcedir": + case "uploadSourceDir": return target.getUploadSourceDir(); case "useglobalsslcontextparameters": case "useGlobalSslContextParameters": return target.isUseGlobalSslContextParameters(); default: return null; diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json index 0fe6ab967ee..66eff52bf6b 100644 --- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json +++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json @@ -195,6 +195,7 @@ { "name": "camel.management.authenticationPath", "description": "Set HTTP url path of embedded server that is protected by authentication configuration.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.management.basicPropertiesFile", "description": "Name of the file that contains basic authentication info for Vert.x file auth provider.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.management.devConsoleEnabled", "description": "Whether to enable developer console (not intended for production use). Dev console must also be enabled on CamelContext. For example by setting camel.context.dev-console=true in application.properties, or via code camelContext.setDevConsole(true); If enabled then you can access a basic developer console on context-path: \/q\/dev.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": [...] + { "name": "camel.management.downloadEnabled", "description": "Whether to enable file download via HTTP. This makes it possible to browse and download resource source files such as Camel XML or YAML routes. Only enable this for development, troubleshooting or special situations for management and monitoring.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.management.enabled", "description": "Whether embedded HTTP server is enabled. By default, the server is not enabled.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.management.healthCheckEnabled", "description": "Whether to enable health-check console. If enabled then you can access health-check status on context-path: \/q\/health (default)", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.management.healthPath", "description": "The path endpoint used to expose the health status", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "\/observe\/health" }, @@ -207,8 +208,10 @@ { "name": "camel.management.jwtKeystoreType", "description": "Type of the keystore used for JWT tokens validation (jks, pkcs12, etc.).", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.management.metricsEnabled", "description": "Whether to enable metrics. If enabled then you can access metrics on context-path: \/q\/metrics (default)", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.management.path", "description": "Context-path to use for embedded HTTP server", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "\/" }, - { "name": "camel.management.port", "description": "Port to use for binding embedded HTTP server", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 9876 }, + { "name": "camel.management.port", "description": "Port to use for binding embedded HTTP server", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "integer", "javaType": "int", "defaultValue": 8080 }, { "name": "camel.management.sendEnabled", "description": "Whether to enable sending messages to Camel via HTTP. This makes it possible to use Camel to send messages to Camel endpoint URIs via HTTP.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, + { "name": "camel.management.uploadEnabled", "description": "Whether to enable file upload via HTTP (not intended for production use). This functionality is for development to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can upload\/delete files via HTTP PUT\/DELETE on context-path: \/q\/upload\/{name}. You must also configure the uploadSourceDir option.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationP [...] + { "name": "camel.management.uploadSourceDir", "description": "Source directory when upload is enabled.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.management.useGlobalSslContextParameters", "description": "Whether to use global SSL configuration for securing the embedded HTTP server.", "sourceType": "org.apache.camel.main.HttpManagementServerConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.metrics.baseEndpointURIExchangeEventNotifier", "description": "Whether to use static or dynamic values for Endpoint Name tags in captured metrics. By default, static values are used. When using dynamic tags, then a dynamic to (toD) can compute many different endpoint URIs that, can lead to many tags as the URI is dynamic, so use this with care if setting this option to false.", "sourceType": "org.apache.camel.main.MetricsConfigurationProperties", "type": "boolean", " [...] { "name": "camel.metrics.binders", "description": "Additional Micrometer binders to include such as jvm-memory, processor, jvm-thread, and so forth. Multiple binders can be separated by comma. The following binders currently is available from Micrometer: class-loader, commons-object-pool2, file-descriptor, hystrix-metrics-binder, jvm-compilation, jvm-gc, jvm-heap-pressure, jvm-info, jvm-memory, jvm-thread, log4j2, logback, processor, uptime", "sourceType": "org.apache.camel.main.Metr [...] diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc index f50aa19a745..fdeffb691d2 100644 --- a/core/camel-main/src/main/docs/main.adoc +++ b/core/camel-main/src/main/docs/main.adoc @@ -215,7 +215,7 @@ The camel.server supports 17 options, which are listed below. === Camel Embedded HTTP management Server (only for standalone; not Spring Boot or Quarkus) configurations -The camel.management supports 19 options, which are listed below. +The camel.management supports 22 options, which are listed below. [width="100%",cols="2,5,^1,2",options="header"] |=== @@ -224,6 +224,7 @@ The camel.management supports 19 options, which are listed below. | *camel.management.authentication{zwsp}Path* | Set HTTP url path of embedded server that is protected by authentication configuration. | | String | *camel.management.basic{zwsp}PropertiesFile* | Name of the file that contains basic authentication info for Vert.x file auth provider. | | String | *camel.management.devConsole{zwsp}Enabled* | Whether to enable developer console (not intended for production use). Dev console must also be enabled on CamelContext. For example by setting camel.context.dev-console=true in application.properties, or via code camelContext.setDevConsole(true); If enabled then you can access a basic developer console on context-path: /q/dev. | false | boolean +| *camel.management.download{zwsp}Enabled* | Whether to enable file download via HTTP. This makes it possible to browse and download resource source files such as Camel XML or YAML routes. Only enable this for development, troubleshooting or special situations for management and monitoring. | false | boolean | *camel.management.enabled* | Whether embedded HTTP server is enabled. By default, the server is not enabled. | false | boolean | *camel.management.healthCheck{zwsp}Enabled* | Whether to enable health-check console. If enabled then you can access health-check status on context-path: /q/health (default) | false | boolean | *camel.management.healthPath* | The path endpoint used to expose the health status | /observe/health | String @@ -236,8 +237,10 @@ The camel.management supports 19 options, which are listed below. | *camel.management.jwtKeystore{zwsp}Type* | Type of the keystore used for JWT tokens validation (jks, pkcs12, etc.). | | String | *camel.management.metrics{zwsp}Enabled* | Whether to enable metrics. If enabled then you can access metrics on context-path: /q/metrics (default) | false | boolean | *camel.management.path* | Context-path to use for embedded HTTP server | / | String -| *camel.management.port* | Port to use for binding embedded HTTP server | 9876 | int +| *camel.management.port* | Port to use for binding embedded HTTP server | 8080 | int | *camel.management.sendEnabled* | Whether to enable sending messages to Camel via HTTP. This makes it possible to use Camel to send messages to Camel endpoint URIs via HTTP. | false | boolean +| *camel.management.uploadEnabled* | Whether to enable file upload via HTTP (not intended for production use). This functionality is for development to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can upload/delete files via HTTP PUT/DELETE on context-path: /q/upload/\{name}. You must also configure the uploadSourceDir option. | false | boolean +| *camel.management.uploadSource{zwsp}Dir* | Source directory when upload is enabled. | | String | *camel.management.useGlobalSsl{zwsp}ContextParameters* | Whether to use global SSL configuration for securing the embedded HTTP server. | false | boolean |=== diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java index 1aa95e34c7b..757ed18f023 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java @@ -1444,6 +1444,12 @@ public abstract class BaseMainSupport extends BaseService { mainConfigurationProperties.isAutoConfigurationFailFast(), true, autoConfiguredProperties); camelContext.setRestConfiguration(rest); } + if (!httpServerProperties.isEmpty() || mainConfigurationProperties.hasHttpServerConfiguration()) { + LOG.debug("Auto-configuring HTTP Server from loaded properties: {}", httpServerProperties.size()); + setHttpServerProperties(camelContext, httpServerProperties, + mainConfigurationProperties.isAutoConfigurationFailFast(), + autoConfiguredProperties); + } if (!httpManagementServerProperties.isEmpty() || mainConfigurationProperties.hasHttpManagementServerConfiguration()) { LOG.debug("Auto-configuring HTTP Management Server from loaded properties: {}", httpManagementServerProperties.size()); @@ -1451,12 +1457,6 @@ public abstract class BaseMainSupport extends BaseService { mainConfigurationProperties.isAutoConfigurationFailFast(), autoConfiguredProperties); } - if (!httpServerProperties.isEmpty() || mainConfigurationProperties.hasHttpServerConfiguration()) { - LOG.debug("Auto-configuring HTTP Server from loaded properties: {}", httpServerProperties.size()); - setHttpServerProperties(camelContext, httpServerProperties, - mainConfigurationProperties.isAutoConfigurationFailFast(), - autoConfiguredProperties); - } if (!threadPoolProperties.isEmpty() || mainConfigurationProperties.hasThreadPoolConfiguration()) { LOG.debug("Auto-configuring Thread Pool from loaded properties: {}", threadPoolProperties.size()); MainSupportModelConfigurer.setThreadPoolProperties(camelContext, mainConfigurationProperties, threadPoolProperties, diff --git a/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java index a157c0e35a2..a18d01e078c 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/HttpManagementServerConfigurationProperties.java @@ -32,8 +32,8 @@ public class HttpManagementServerConfigurationProperties implements BootstrapClo private boolean enabled; @Metadata(defaultValue = "0.0.0.0") private String host = "0.0.0.0"; - @Metadata(defaultValue = "9876") - private int port = 9876; + @Metadata(defaultValue = "8080") + private int port = 8080; @Metadata(defaultValue = "/") private String path = "/"; @Metadata(defaultValue = "/observe/health") @@ -46,6 +46,9 @@ public class HttpManagementServerConfigurationProperties implements BootstrapClo private boolean healthCheckEnabled; private boolean jolokiaEnabled; private boolean metricsEnabled; + private boolean uploadEnabled; + private String uploadSourceDir; + private boolean downloadEnabled; private boolean sendEnabled; @Metadata(label = "security") @@ -212,6 +215,44 @@ public class HttpManagementServerConfigurationProperties implements BootstrapClo this.jolokiaPath = jolokiaPath; } + public boolean isUploadEnabled() { + return uploadEnabled; + } + + /** + * Whether to enable file upload via HTTP (not intended for production use). This functionality is for development + * to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can + * upload/delete files via HTTP PUT/DELETE on context-path: /q/upload/{name}. You must also configure the + * uploadSourceDir option. + */ + public void setUploadEnabled(boolean uploadEnabled) { + this.uploadEnabled = uploadEnabled; + } + + public String getUploadSourceDir() { + return uploadSourceDir; + } + + /** + * Source directory when upload is enabled. + */ + public void setUploadSourceDir(String uploadSourceDir) { + this.uploadSourceDir = uploadSourceDir; + } + + public boolean isDownloadEnabled() { + return downloadEnabled; + } + + /** + * Whether to enable file download via HTTP. This makes it possible to browse and download resource source files + * such as Camel XML or YAML routes. Only enable this for development, troubleshooting or special situations for + * management and monitoring. + */ + public void setDownloadEnabled(boolean downloadEnabled) { + this.downloadEnabled = downloadEnabled; + } + public boolean isSendEnabled() { return sendEnabled; } @@ -376,6 +417,35 @@ public class HttpManagementServerConfigurationProperties implements BootstrapClo return this; } + /** + * Whether to enable file upload via HTTP (not intended for production use). This functionality is for development + * to be able to reload Camel routes and code with source changes (if reload is enabled). If enabled then you can + * upload/delete files via HTTP PUT/DELETE on context-path: /q/upload/{name}. You must also configure the + * uploadSourceDir option. + */ + public HttpManagementServerConfigurationProperties withUploadEnabled(boolean uploadEnabled) { + this.uploadEnabled = uploadEnabled; + return this; + } + + /** + * Source directory when upload is enabled. + */ + public HttpManagementServerConfigurationProperties withUploadSourceDir(String uploadSourceDir) { + this.uploadSourceDir = uploadSourceDir; + return this; + } + + /** + * Whether to enable file download via HTTP. This makes it possible to browse and download resource source files + * such as Camel XML or YAML routes. Only enable this for development, troubleshooting or special situations for + * management and monitoring. + */ + public HttpManagementServerConfigurationProperties withDownloadEnabled(boolean downloadEnabled) { + this.downloadEnabled = downloadEnabled; + return this; + } + /** * Whether to enable sending messages to Camel via HTTP. This makes it possible to use Camel to send messages to * Camel endpoint URIs via HTTP.
