From 34a7a6a6cd9f90ffd13c9ac3513f979b085e0209 Mon Sep 17 00:00:00 2001 From: Phillip Kruger Date: Mon, 30 May 2022 11:11:47 +1000 Subject: [PATCH] Added new Filter to automatically set the server in the OpenAPI Schema Signed-off-by: Phillip Kruger --- .../deployment/SmallRyeOpenApiConfig.java | 7 ++ .../deployment/SmallRyeOpenApiProcessor.java | 37 +++++++- .../deployment/filter/AutoServerFilter.java | 87 +++++++++++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/filter/AutoServerFilter.java 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 e2ac9f95005813..2231b7967cd0c2 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 @@ -71,6 +71,13 @@ public final class SmallRyeOpenApiConfig { @ConfigItem(defaultValue = "true") public boolean autoAddTags; + /** + * This will automatically add a default server to the schema if non is provided, using the current running server host and + * port. + */ + @ConfigItem + public Optional autoAddServer; + /** * This will automatically add security based on the security extension included (if any). */ 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 283991a5796eff..216248e4b8e6c3 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 @@ -7,6 +7,7 @@ import java.io.InputStreamReader; import java.io.UncheckedIOException; import java.lang.reflect.Modifier; +import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -81,6 +82,7 @@ import io.quarkus.security.Authenticated; import io.quarkus.smallrye.openapi.common.deployment.SmallRyeOpenApiConfig; import io.quarkus.smallrye.openapi.deployment.filter.AutoRolesAllowedFilter; +import io.quarkus.smallrye.openapi.deployment.filter.AutoServerFilter; import io.quarkus.smallrye.openapi.deployment.filter.AutoTagFilter; import io.quarkus.smallrye.openapi.deployment.filter.SecurityConfigFilter; import io.quarkus.smallrye.openapi.deployment.spi.AddToOpenAPIDefinitionBuildItem; @@ -290,9 +292,9 @@ OpenApiFilteredIndexViewBuildItem smallryeOpenApiIndex(CombinedIndexBuildItem co } @BuildStep - void addSecurityFilter(BuildProducer addToOpenAPIDefinitionProducer, + void addAutoFilters(BuildProducer addToOpenAPIDefinitionProducer, OpenApiFilteredIndexViewBuildItem apiFilteredIndexViewBuildItem, - SmallRyeOpenApiConfig config) { + SmallRyeOpenApiConfig config) throws MalformedURLException { List rolesAllowedAnnotations = new ArrayList<>(); for (DotName rolesAllowed : SecurityConstants.ROLES_ALLOWED) { @@ -343,6 +345,11 @@ void addSecurityFilter(BuildProducer addToOpenA addToOpenAPIDefinitionProducer.produce(new AddToOpenAPIDefinitionBuildItem(autoTagFilter)); } + // Add Auto Server based on the current server details + OASFilter autoServerFilter = getAutoServerFilter(config, false); + if (autoServerFilter != null) { + addToOpenAPIDefinitionProducer.produce(new AddToOpenAPIDefinitionBuildItem(autoServerFilter)); + } } private OASFilter getAutoSecurityFilter(List securityInformationBuildItems, @@ -440,6 +447,27 @@ private OASFilter getAutoTagFilter(OpenApiFilteredIndexViewBuildItem apiFiltered return null; } + private OASFilter getAutoServerFilter(SmallRyeOpenApiConfig config, boolean defaultFlag) throws MalformedURLException { + if (config.autoAddServer.orElse(defaultFlag)) { + Config c = ConfigProvider.getConfig(); + + String scheme = "http"; + String host = c.getOptionalValue("quarkus.http.host", String.class).orElse("0.0.0.0"); + int port; + + String insecure = c.getOptionalValue("quarkus.http.insecure-requests", String.class).orElse("enabled"); + if (insecure.equalsIgnoreCase("enabled")) { + port = c.getOptionalValue("quarkus.http.port", Integer.class).orElse(8080); + } else { + scheme = "https"; + port = c.getOptionalValue("quarkus.http.ssl-port", Integer.class).orElse(8443); + } + + return new AutoServerFilter(scheme, host, port); + } + return null; + } + private Map> getRolesAllowedMethodReferences( OpenApiFilteredIndexViewBuildItem apiFilteredIndexViewBuildItem) { List rolesAllowedAnnotations = new ArrayList<>(); @@ -976,6 +1004,11 @@ private OpenApiDocument storeDocument(OutputTargetBuildItem out, OpenApiDocument document = prepareOpenApiDocument(staticModel, annotationModel, openAPIBuildItems); document.filter(filter(openApiConfig)); // This usually happens at runtime, so when storing we want to filter here too. + // By default also add the auto generated server + OASFilter autoServerFilter = getAutoServerFilter(smallRyeOpenApiConfig, true); + if (autoServerFilter != null) { + document.filter(autoServerFilter); + } document.initialize(); // Store the document if needed diff --git a/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/filter/AutoServerFilter.java b/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/filter/AutoServerFilter.java new file mode 100644 index 00000000000000..7c4be3aecee737 --- /dev/null +++ b/extensions/smallrye-openapi/deployment/src/main/java/io/quarkus/smallrye/openapi/deployment/filter/AutoServerFilter.java @@ -0,0 +1,87 @@ +package io.quarkus.smallrye.openapi.deployment.filter; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.microprofile.openapi.OASFilter; +import org.eclipse.microprofile.openapi.models.OpenAPI; +import org.eclipse.microprofile.openapi.models.servers.Server; + +import io.smallrye.openapi.api.models.servers.ServerImpl; + +/** + * Automatically add default server if none is provided + */ +public class AutoServerFilter implements OASFilter { + + private static final String DESCRIPTION = "Auto generated value"; + private static final String ZEROS = "0.0.0.0"; + private static final String LOCALHOST = "localhost"; + private static final String URL_PATTERN = "%s://%s:%d"; + + private String defaultScheme; + private String defaultHost; + private int defaultPort; + + public AutoServerFilter() { + + } + + public AutoServerFilter(String defaultScheme, String defaultHost, int defaultPort) { + this.defaultScheme = defaultScheme; + this.defaultHost = defaultHost; + this.defaultPort = defaultPort; + } + + public String getDefaultScheme() { + return defaultScheme; + } + + public void setDefaultScheme(String defaultScheme) { + this.defaultScheme = defaultScheme; + } + + public String getDefaultHost() { + return defaultHost; + } + + public void setDefaultHost(String defaultHost) { + this.defaultHost = defaultHost; + } + + public int getDefaultPort() { + return defaultPort; + } + + public void setDefaultPort(int defaultPort) { + this.defaultPort = defaultPort; + } + + @Override + public void filterOpenAPI(OpenAPI openAPI) { + + List servers = openAPI.getServers(); + if (servers == null || servers.isEmpty()) { + servers = new ArrayList<>(); + + // In case of 0.0.0.0, also add localhost + if (this.defaultHost.equals(ZEROS)) { + ServerImpl localhost = new ServerImpl(); + localhost.setUrl(getUrl(this.defaultScheme, LOCALHOST, this.defaultPort)); + localhost.setDescription(DESCRIPTION); + servers.add(localhost); + } + + ServerImpl serverImpl = new ServerImpl(); + serverImpl.setUrl(getUrl(this.defaultScheme, this.defaultHost, this.defaultPort)); + serverImpl.setDescription(DESCRIPTION); + servers.add(serverImpl); + + openAPI.setServers(servers); + } + } + + private String getUrl(String scheme, String host, int port) { + return String.format(URL_PATTERN, scheme, host, port); + } +}