From 40b2157a919c0cd0bc940550b6853d04ae82ee2c Mon Sep 17 00:00:00 2001 From: Phillip Kruger Date: Tue, 11 Jul 2023 13:09:27 +1000 Subject: [PATCH] Add OpenAPI to management interface if enabled, with option to exclude Signed-off-by: Phillip Kruger --- .../devui/SmallRyeGraphQLDevUIProcessor.java | 7 +++--- .../deployment/SmallRyeHealthConfig.java | 7 ++++++ .../SmallRyeHealthDevUiProcessor.java | 11 +++++---- .../deployment/SmallRyeHealthProcessor.java | 18 ++++++++------- .../deployment/SmallRyeOpenApiConfig.java | 7 ++++++ .../deployment/SmallRyeOpenApiProcessor.java | 4 ++++ .../devui/OpenApiDevUIProcessor.java | 23 ++++++++++++------- .../deployment/SwaggerUiProcessor.java | 8 ++++++- .../deployment/HttpRootPathBuildItem.java | 6 +++++ .../NonApplicationRootPathBuildItem.java | 22 +++++++++++++----- .../vertx/http/deployment/RouteBuildItem.java | 18 ++++++++++++++- .../resources/dev-ui/qwc/qwc-external-page.js | 2 +- .../devui/spi/page/ExternalPageBuilder.java | 8 +++++++ 13 files changed, 108 insertions(+), 33 deletions(-) diff --git a/extensions/smallrye-graphql/deployment/src/main/java/io/quarkus/smallrye/graphql/deployment/devui/SmallRyeGraphQLDevUIProcessor.java b/extensions/smallrye-graphql/deployment/src/main/java/io/quarkus/smallrye/graphql/deployment/devui/SmallRyeGraphQLDevUIProcessor.java index fc960b8ffeba0b..495a617a5cf239 100644 --- a/extensions/smallrye-graphql/deployment/src/main/java/io/quarkus/smallrye/graphql/deployment/devui/SmallRyeGraphQLDevUIProcessor.java +++ b/extensions/smallrye-graphql/deployment/src/main/java/io/quarkus/smallrye/graphql/deployment/devui/SmallRyeGraphQLDevUIProcessor.java @@ -18,17 +18,16 @@ CardPageBuildItem createCard(NonApplicationRootPathBuildItem nonApplicationRootP CardPageBuildItem cardPageBuildItem = new CardPageBuildItem(); // Generated GraphQL Schema + String schemaPath = "/" + graphQLConfig.rootPath + "/schema.graphql"; PageBuilder schemaPage = Page.externalPageBuilder("GraphQL Schema") .icon("font-awesome-solid:diagram-project") - .url("/" + graphQLConfig.rootPath + "/schema.graphql"); + .url(schemaPath, schemaPath); // GraphiQL UI String uiPath = nonApplicationRootPathBuildItem.resolvePath(graphQLConfig.ui.rootPath); PageBuilder uiPage = Page.externalPageBuilder("GraphQL UI") .icon("font-awesome-solid:table-columns") - .staticLabel("") - .url(uiPath + "/index.html?embed=true"); + .url(uiPath + "/index.html?embed=true", uiPath); // Learn PageBuilder learnLink = Page.externalPageBuilder("Learn more about GraphQL") diff --git a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthConfig.java b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthConfig.java index ee1f47b536bab0..79a941fa3e3ce6 100644 --- a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthConfig.java +++ b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthConfig.java @@ -72,6 +72,13 @@ public class SmallRyeHealthConfig { @ConfigItem Optional defaultHealthGroup; + /** + * If management interface is turned on the health endpoints and ui will be published under the management interface. This + * allows you to exclude Health from management by setting the value to false + */ + @ConfigItem(name = "management.enabled", defaultValue = "true") + public boolean managementEnabled; + /** * SmallRye Health UI configuration */ diff --git a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthDevUiProcessor.java b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthDevUiProcessor.java index c6909315a1a8d6..4a9f5b2f79d92e 100644 --- a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthDevUiProcessor.java +++ b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthDevUiProcessor.java @@ -25,16 +25,19 @@ CardPageBuildItem create(NonApplicationRootPathBuildItem nonApplicationRootPathB SmallRyeHealthRecorder unused) { CardPageBuildItem pageBuildItem = new CardPageBuildItem(); - var path = nonApplicationRootPathBuildItem.resolveManagementPath(config.rootPath, - managementInterfaceBuildTimeConfig, launchModeBuildItem); + String path = nonApplicationRootPathBuildItem.resolveManagementPath(config.rootPath, + managementInterfaceBuildTimeConfig, launchModeBuildItem, config.managementEnabled); + pageBuildItem.addPage(Page.externalPageBuilder("Health") .icon("font-awesome-solid:heart-circle-bolt") - .url(path) + .url(path, path) .isJsonContent()); + String uipath = nonApplicationRootPathBuildItem.resolveManagementPath(config.ui.rootPath, + managementInterfaceBuildTimeConfig, launchModeBuildItem, config.managementEnabled); pageBuildItem.addPage(Page.externalPageBuilder("Health UI") .icon("font-awesome-solid:stethoscope") - .url(nonApplicationRootPathBuildItem.resolvePath(config.ui.rootPath)) + .url(uipath, uipath) .isHtmlContent()); return pageBuildItem; diff --git a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java index 8b8a35a6ba640c..1281337f62a5fd 100644 --- a/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java +++ b/extensions/smallrye-health/deployment/src/main/java/io/quarkus/smallrye/health/deployment/SmallRyeHealthProcessor.java @@ -208,7 +208,7 @@ public void defineHealthRoutes(BuildProducer routes, // Register the health handler routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management() + .management("quarkus.smallrye-health.management.enabled") .route(healthConfig.rootPath) .routeConfigKey("quarkus.smallrye-health.root-path") .handler(new SmallRyeHealthHandler()) @@ -218,7 +218,7 @@ public void defineHealthRoutes(BuildProducer routes, // Register the liveness handler routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management() + .management("quarkus.smallrye-health.management.enabled") .nestedRoute(healthConfig.rootPath, healthConfig.livenessPath) .handler(new SmallRyeLivenessHandler()) .displayOnNotFoundPage() @@ -227,7 +227,7 @@ public void defineHealthRoutes(BuildProducer routes, // Register the readiness handler routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management() + .management("quarkus.smallrye-health.management.enabled") .nestedRoute(healthConfig.rootPath, healthConfig.readinessPath) .handler(new SmallRyeReadinessHandler()) .displayOnNotFoundPage() @@ -249,7 +249,7 @@ public void defineHealthRoutes(BuildProducer routes, // Register the health group handlers routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management() + .management("quarkus.smallrye-health.management.enabled") .nestedRoute(healthConfig.rootPath, healthConfig.groupPath) .handler(new SmallRyeHealthGroupHandler()) .displayOnNotFoundPage() @@ -258,7 +258,7 @@ public void defineHealthRoutes(BuildProducer routes, SmallRyeIndividualHealthGroupHandler handler = new SmallRyeIndividualHealthGroupHandler(); routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management() + .management("quarkus.smallrye-health.management.enabled") .nestedRoute(healthConfig.rootPath, healthConfig.groupPath + "/*") .handler(handler) .displayOnNotFoundPage() @@ -267,7 +267,7 @@ public void defineHealthRoutes(BuildProducer routes, // Register the wellness handler routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management() + .management("quarkus.smallrye-health.management.enabled") .nestedRoute(healthConfig.rootPath, healthConfig.wellnessPath) .handler(new SmallRyeWellnessHandler()) .displayOnNotFoundPage() @@ -276,7 +276,7 @@ public void defineHealthRoutes(BuildProducer routes, // Register the startup handler routes.produce(nonApplicationRootPathBuildItem.routeBuilder() - .management() + .management("quarkus.smallrye-health.management.enabled") .nestedRoute(healthConfig.rootPath, healthConfig.startupPath) .handler(new SmallRyeStartupHandler()) .displayOnNotFoundPage() @@ -443,8 +443,9 @@ void registerHealthUiHandler( Handler handler = recorder.uiHandler(result.getFinalDestination(), healthUiPath, result.getWebRootConfigurations(), runtimeConfig, shutdownContext); - // The health ui is not a management route. + routeProducer.produce(nonApplicationRootPathBuildItem.routeBuilder() + .management("quarkus.smallrye-health.management.enabled") .route(healthConfig.ui.rootPath) .displayOnNotFoundPage("Health UI") .routeConfigKey("quarkus.smallrye-health.ui.root-path") @@ -452,6 +453,7 @@ void registerHealthUiHandler( .build()); routeProducer.produce(nonApplicationRootPathBuildItem.routeBuilder() + .management("quarkus.smallrye-health.management.enabled") .route(healthConfig.ui.rootPath + "*") .handler(handler) .build()); diff --git a/extensions/smallrye-openapi-common/deployment/src/main/java/io/quarkus/smallrye/openapi/common/deployment/SmallRyeOpenApiConfig.java b/extensions/smallrye-openapi-common/deployment/src/main/java/io/quarkus/smallrye/openapi/common/deployment/SmallRyeOpenApiConfig.java index 9e9f11f99cc0d8..59c333fc96e202 100644 --- a/extensions/smallrye-openapi-common/deployment/src/main/java/io/quarkus/smallrye/openapi/common/deployment/SmallRyeOpenApiConfig.java +++ b/extensions/smallrye-openapi-common/deployment/src/main/java/io/quarkus/smallrye/openapi/common/deployment/SmallRyeOpenApiConfig.java @@ -37,6 +37,13 @@ public final class SmallRyeOpenApiConfig { @ConfigItem(defaultValue = "false") public boolean ignoreStaticDocument; + /** + * If management interface is turned on the openapi schema document will be published under the management interface. This + * allows you to exclude OpenAPI from management by setting the value to false + */ + @ConfigItem(name = "management.enabled", defaultValue = "true") + public boolean managementEnabled; + /** * A list of local directories that should be scanned for yaml and/or json files to be included in the static model. * Example: `META-INF/openapi/` diff --git a/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/SmallRyeOpenApiProcessor.java b/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/SmallRyeOpenApiProcessor.java index 5d9e6b6a220e17..a24126bb92ebb7 100644 --- a/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/SmallRyeOpenApiProcessor.java +++ b/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/SmallRyeOpenApiProcessor.java @@ -271,6 +271,7 @@ void handler(LaunchModeBuildItem launch, } routes.produce(nonApplicationRootPathBuildItem.routeBuilder() + .management("quarkus.smallrye-openapi.management.enabled") .routeFunction(openApiConfig.path, corsFilter) .routeConfigKey("quarkus.smallrye-openapi.path") .handler(handler) @@ -279,16 +280,19 @@ void handler(LaunchModeBuildItem launch, .build()); routes.produce(nonApplicationRootPathBuildItem.routeBuilder() + .management("quarkus.smallrye-openapi.management.enabled") .routeFunction(openApiConfig.path + ".json", corsFilter) .handler(handler) .build()); routes.produce(nonApplicationRootPathBuildItem.routeBuilder() + .management("quarkus.smallrye-openapi.management.enabled") .routeFunction(openApiConfig.path + ".yaml", corsFilter) .handler(handler) .build()); routes.produce(nonApplicationRootPathBuildItem.routeBuilder() + .management("quarkus.smallrye-openapi.management.enabled") .routeFunction(openApiConfig.path + ".yml", corsFilter) .handler(handler) .build()); diff --git a/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/devui/OpenApiDevUIProcessor.java b/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/devui/OpenApiDevUIProcessor.java index 3e5cc8b6080518..52602cfb894dcd 100644 --- a/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/devui/OpenApiDevUIProcessor.java +++ b/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/devui/OpenApiDevUIProcessor.java @@ -2,37 +2,44 @@ import io.quarkus.deployment.IsDevelopment; import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.LaunchModeBuildItem; import io.quarkus.devui.spi.page.CardPageBuildItem; import io.quarkus.devui.spi.page.Page; import io.quarkus.smallrye.openapi.common.deployment.SmallRyeOpenApiConfig; import io.quarkus.swaggerui.deployment.SwaggerUiConfig; import io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem; +import io.quarkus.vertx.http.runtime.management.ManagementInterfaceBuildTimeConfig; public class OpenApiDevUIProcessor { @BuildStep(onlyIf = IsDevelopment.class) public CardPageBuildItem pages(NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem, - SwaggerUiConfig swaggerUiConfig, SmallRyeOpenApiConfig openApiConfig) { + ManagementInterfaceBuildTimeConfig managementInterfaceBuildTimeConfig, + LaunchModeBuildItem launchModeBuildItem, + SwaggerUiConfig swaggerUiConfig, + SmallRyeOpenApiConfig openApiConfig) { - String uiPath = nonApplicationRootPathBuildItem.resolvePath(swaggerUiConfig.path); - String schemaPath = nonApplicationRootPathBuildItem.resolvePath(openApiConfig.path); + String uiPath = nonApplicationRootPathBuildItem.resolveManagementPath(swaggerUiConfig.path, + managementInterfaceBuildTimeConfig, launchModeBuildItem, openApiConfig.managementEnabled); + + String schemaPath = nonApplicationRootPathBuildItem.resolveManagementPath(openApiConfig.path, + managementInterfaceBuildTimeConfig, launchModeBuildItem, openApiConfig.managementEnabled); CardPageBuildItem cardPageBuildItem = new CardPageBuildItem(); cardPageBuildItem.addPage(Page.externalPageBuilder("Schema yaml") - .url(nonApplicationRootPathBuildItem.resolvePath(schemaPath)) + .url(schemaPath, schemaPath) .isYamlContent() .icon("font-awesome-solid:file-lines")); + String jsonSchema = schemaPath + "?format=json"; cardPageBuildItem.addPage(Page.externalPageBuilder("Schema json") - .url(nonApplicationRootPathBuildItem.resolvePath(schemaPath) + "?format=json") + .url(jsonSchema, jsonSchema) .isJsonContent() .icon("font-awesome-solid:file-code")); cardPageBuildItem.addPage(Page.externalPageBuilder("Swagger UI") - .url(uiPath + "/index.html?embed=true") - .staticLabel("") + .url(uiPath + "/index.html?embed=true", uiPath) .isHtmlContent() .icon("font-awesome-solid:signs-post")); diff --git a/extensions/swagger-ui/deployment/src/main/java/io/quarkus/swaggerui/deployment/SwaggerUiProcessor.java b/extensions/swagger-ui/deployment/src/main/java/io/quarkus/swaggerui/deployment/SwaggerUiProcessor.java index e04a0abb8e18de..8b392141a262a5 100644 --- a/extensions/swagger-ui/deployment/src/main/java/io/quarkus/swaggerui/deployment/SwaggerUiProcessor.java +++ b/extensions/swagger-ui/deployment/src/main/java/io/quarkus/swaggerui/deployment/SwaggerUiProcessor.java @@ -37,6 +37,7 @@ import io.quarkus.vertx.http.deployment.webjar.WebJarBuildItem; import io.quarkus.vertx.http.deployment.webjar.WebJarResourcesFilter; import io.quarkus.vertx.http.deployment.webjar.WebJarResultsBuildItem; +import io.quarkus.vertx.http.runtime.management.ManagementInterfaceBuildTimeConfig; import io.smallrye.openapi.ui.IndexHtmlCreator; import io.smallrye.openapi.ui.Option; import io.smallrye.openapi.ui.ThemeHref; @@ -86,6 +87,7 @@ List brandingFiles() { @BuildStep public void getSwaggerUiFinalDestination( NonApplicationRootPathBuildItem nonApplicationRootPathBuildItem, + ManagementInterfaceBuildTimeConfig managementInterfaceBuildTimeConfig, LaunchModeBuildItem launchMode, SwaggerUiConfig swaggerUiConfig, SmallRyeOpenApiConfig openapi, @@ -119,7 +121,9 @@ public void getSwaggerUiFinalDestination( } } - String openApiPath = nonApplicationRootPathBuildItem.resolvePath(openapi.path); + String openApiPath = nonApplicationRootPathBuildItem.resolveManagementPath(openapi.path, + managementInterfaceBuildTimeConfig, launchMode, openapi.managementEnabled); + String swaggerUiPath = nonApplicationRootPathBuildItem.resolvePath(swaggerUiConfig.path); ThemeHref theme = swaggerUiConfig.theme.orElse(ThemeHref.feeling_blue); @@ -180,6 +184,7 @@ public void registerSwaggerUiHandler(SwaggerUiRecorder recorder, runtimeConfig, shutdownContext); routes.produce(nonApplicationRootPathBuildItem.routeBuilder() + .management("quarkus.smallrye-openapi.management.enabled") .route(swaggerUiConfig.path) .displayOnNotFoundPage("Open API UI") .routeConfigKey("quarkus.swagger-ui.path") @@ -187,6 +192,7 @@ public void registerSwaggerUiHandler(SwaggerUiRecorder recorder, .build()); routes.produce(nonApplicationRootPathBuildItem.routeBuilder() + .management("quarkus.smallrye-openapi.management.enabled") .route(swaggerUiConfig.path + "*") .handler(handler) .build()); diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpRootPathBuildItem.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpRootPathBuildItem.java index 451c50593da56a..b5219b0166461b 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpRootPathBuildItem.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpRootPathBuildItem.java @@ -224,6 +224,12 @@ public Builder management() { return this; } + @Override + public Builder management(String managementConfigKey) { + super.management(managementConfigKey); + return this; + } + @Override protected NotFoundPageDisplayableEndpointBuildItem getNotFoundEndpoint() { return super.getNotFoundEndpoint(); diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/NonApplicationRootPathBuildItem.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/NonApplicationRootPathBuildItem.java index 67ecf5846ef9ab..1eea2aa28a2670 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/NonApplicationRootPathBuildItem.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/NonApplicationRootPathBuildItem.java @@ -169,15 +169,15 @@ public String resolvePath(String path) { public String resolveManagementPath(String path, ManagementInterfaceBuildTimeConfig managementInterfaceBuildTimeConfig, LaunchModeBuildItem mode) { + return resolveManagementPath(path, managementInterfaceBuildTimeConfig, mode, true); + } + + public String resolveManagementPath(String path, ManagementInterfaceBuildTimeConfig managementInterfaceBuildTimeConfig, + LaunchModeBuildItem mode, boolean extensionOverride) { if (path == null || path.trim().isEmpty()) { throw new IllegalArgumentException("Specified path can not be empty"); } - if (!managementInterfaceBuildTimeConfig.enabled) { - if (managementRootPath != null) { - return UriNormalizationUtil.normalizeWithBase(managementRootPath, path, false).getPath(); - } - return UriNormalizationUtil.normalizeWithBase(nonApplicationRootPath, path, false).getPath(); - } else { + if (managementInterfaceBuildTimeConfig.enabled && extensionOverride) { // Best effort String prefix = getManagementUrlPrefix(mode); if (managementRootPath != null) { @@ -185,6 +185,11 @@ public String resolveManagementPath(String path, ManagementInterfaceBuildTimeCon } else { return prefix + path; } + } else { + if (managementRootPath != null) { + return UriNormalizationUtil.normalizeWithBase(managementRootPath, path, false).getPath(); + } + return UriNormalizationUtil.normalizeWithBase(nonApplicationRootPath, path, false).getPath(); } } @@ -411,6 +416,11 @@ public Builder management() { return this; } + @Override + public Builder management(String managementConfigKey) { + super.management(managementConfigKey); + return this; + } } /** diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/RouteBuildItem.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/RouteBuildItem.java index f4f985baee2469..2fc29dad313967 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/RouteBuildItem.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/RouteBuildItem.java @@ -5,6 +5,9 @@ import java.util.function.Consumer; import java.util.function.Function; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; + import io.quarkus.builder.item.MultiBuildItem; import io.quarkus.vertx.http.deployment.devmode.NotFoundPageDisplayableEndpointBuildItem; import io.quarkus.vertx.http.deployment.devmode.console.ConfiguredPathInfo; @@ -210,10 +213,23 @@ public Builder routeConfigKey(String attributeName) { } public Builder management() { - this.isManagement = true; + return management(null); + } + + public Builder management(String managementConfigKey) { + if (managementConfigKey == null || shouldInclude(managementConfigKey)) { + this.isManagement = true; + } else { + this.isManagement = false; + } return this; } + private boolean shouldInclude(String managementConfigKey) { + Config config = ConfigProvider.getConfig(); + return config.getValue(managementConfigKey, boolean.class); + } + public RouteBuildItem build() { if (routeFunction == null) { throw new IllegalStateException( diff --git a/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-external-page.js b/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-external-page.js index c0f99a61d27546..a0baff193e6c5d 100644 --- a/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-external-page.js +++ b/extensions/vertx-http/dev-ui-resources/src/main/resources/dev-ui/qwc/qwc-external-page.js @@ -109,7 +109,7 @@ export class QwcExternalPage extends LitElement { let currentPath = window.location.pathname; currentPath = currentPath.substring(0, currentPath.indexOf('/dev')); return html`
- + Download diff --git a/extensions/vertx-http/dev-ui-spi/src/main/java/io/quarkus/devui/spi/page/ExternalPageBuilder.java b/extensions/vertx-http/dev-ui-spi/src/main/java/io/quarkus/devui/spi/page/ExternalPageBuilder.java index aad52ee93d1cb8..cd778b554a81ce 100644 --- a/extensions/vertx-http/dev-ui-spi/src/main/java/io/quarkus/devui/spi/page/ExternalPageBuilder.java +++ b/extensions/vertx-http/dev-ui-spi/src/main/java/io/quarkus/devui/spi/page/ExternalPageBuilder.java @@ -21,10 +21,18 @@ protected ExternalPageBuilder(String title) { } public ExternalPageBuilder url(String url) { + return url(url, null); + } + + public ExternalPageBuilder url(String url, String externalLink) { if (url == null || url.isEmpty()) { throw new RuntimeException("Invalid external URL, can not be empty"); } super.metadata.put(EXTERNAL_URL, url); + if (externalLink != null) { + return staticLabel(""); + } return this; }