Skip to content

Commit

Permalink
Add ability to set final swagger file path for UI. (#1051)
Browse files Browse the repository at this point in the history
Upgrade libs.
Swagger UI 4.19.0
  • Loading branch information
altro3 authored Jun 15, 2023
1 parent 4215345 commit 287773f
Show file tree
Hide file tree
Showing 20 changed files with 126 additions and 73 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ projectVersion=4.9.1-SNAPSHOT
projectGroup=io.micronaut.openapi

micronautDocsVersion=2.0.0
micronautVersion=3.9.2
micronautVersion=3.9.3
micronautTestVersion=3.9.2
groovyVersion=3.0.17
spockVersion=2.3-groovy-3.0
Expand Down
8 changes: 4 additions & 4 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
[versions]
managed-swagger = "2.2.10"
managed-swagger = "2.2.11"
# Required to keep catalog compatibility with 3.4.x. Can be removed for 4.0.0
managed-swagger-compat = "2.2.10"
managed-swagger-compat = "2.2.11"
managed-javadoc-parser = "0.3.1"
managed-jsoup = "1.16.1"
managed-jakarta-validation-api = "3.0.2"

# Versions beyond 0.62.2 require Java 11
managed-html2md-converter = "0.62.2"

kotlin = "1.8.21"
kotlin-coroutines = "1.7.0"
kotlin = "1.8.22"
kotlin-coroutines = "1.7.1"
jspecify = "0.3.0"
jdt-annotation = "2.2.700"
android-annotation = "1.6.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
import io.micronaut.core.util.StringUtils;
import io.micronaut.inject.visitor.VisitorContext;
import io.micronaut.openapi.visitor.OpenApiApplicationVisitor;
import io.micronaut.openapi.visitor.Utils;

import static io.micronaut.openapi.visitor.OpenApiApplicationVisitor.MICRONAUT_INTERNAL_OPENAPI_FILENAME;

/**
* Abstract View Config.
Expand All @@ -35,6 +38,7 @@ abstract class AbstractViewConfig {

protected String prefix;
protected String jsUrl = "";
protected String specUrl;
protected String finalUrlPrefix;
protected String resourcesContextPath = "/res";
protected String templatePath;
Expand Down Expand Up @@ -108,7 +112,7 @@ protected String getFinalUrlPrefix(OpenApiViewConfig.RendererType rendererType,
}

// process micronaut.server.context-path
String contextPath = OpenApiApplicationVisitor.getConfigurationProperty("micronaut.server.context-path", context);
String contextPath = OpenApiApplicationVisitor.getConfigurationProperty(OpenApiApplicationVisitor.MICRONAUT_SERVER_CONTEXT_PATH, context);
if (contextPath == null) {
contextPath = StringUtils.EMPTY_STRING;
}
Expand Down Expand Up @@ -136,16 +140,23 @@ protected String getFinalUrlPrefix(OpenApiViewConfig.RendererType rendererType,
* @param cfg A View config.
* @param defaultOptions The default options.
* @param properties The options to parse.
* @param context Visitor context.
*
* @return A View config.
*/
static <T extends AbstractViewConfig> T fromProperties(T cfg, Map<String, Object> defaultOptions, Map<String, String> properties) {
static <T extends AbstractViewConfig> T fromProperties(T cfg, Map<String, Object> defaultOptions, Map<String, String> properties, VisitorContext context) {

String copyResources = properties.get(cfg.prefix + "copy-resources");
if (StringUtils.isNotEmpty(copyResources) && "false".equalsIgnoreCase(copyResources)) {
cfg.copyResources = false;
}

String specUrl = properties.get(cfg.prefix + "spec.url");
if (specUrl != null) {
cfg.specUrl = specUrl.replace(Utils.PLACEHOLDER_PREFIX + "filename" + Utils.PLACEHOLDER_POSTFIX,
context != null ? context.get(MICRONAUT_INTERNAL_OPENAPI_FILENAME, String.class).orElse("") : "");
}

String jsUrl = properties.get(cfg.prefix + "js.url");
if (StringUtils.isNotEmpty(jsUrl)) {
cfg.jsUrl = jsUrl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
import io.micronaut.openapi.visitor.OpenApiApplicationVisitor;
import io.micronaut.openapi.visitor.Utils;

import static io.micronaut.openapi.visitor.OpenApiApplicationVisitor.MICRONAUT_SERVER_CONTEXT_PATH;

/**
* OpenApi view configuration for Swagger-ui, ReDoc and RapiDoc.
* By default, no views are enabled.
Expand Down Expand Up @@ -120,25 +122,26 @@ private static Map<String, String> parse(String specification) {
*
* @param specification A String representation of an OpenApiViewConfig.
* @param openApiProperties The open api properties.
* @param context Visitor context.
*
* @return An OpenApiViewConfig.
*/
public static OpenApiViewConfig fromSpecification(String specification, Properties openApiProperties) {
public static OpenApiViewConfig fromSpecification(String specification, Properties openApiProperties, VisitorContext context) {
Map<String, String> openApiMap = new HashMap<>(openApiProperties.size());
openApiProperties.forEach((key, value) -> openApiMap.put((String) key, (String) value));
openApiMap.putAll(parse(specification));
OpenApiViewConfig cfg = new OpenApiViewConfig();
RapiPDFConfig rapiPDFConfig = RapiPDFConfig.fromProperties(openApiMap);
RapiPDFConfig rapiPDFConfig = RapiPDFConfig.fromProperties(openApiMap, context);
if ("true".equals(openApiMap.getOrDefault("redoc.enabled", Boolean.FALSE.toString()))) {
cfg.redocConfig = RedocConfig.fromProperties(openApiMap);
cfg.redocConfig = RedocConfig.fromProperties(openApiMap, context);
cfg.redocConfig.rapiPDFConfig = rapiPDFConfig;
}
if ("true".equals(openApiMap.getOrDefault("rapidoc.enabled", Boolean.FALSE.toString()))) {
cfg.rapidocConfig = RapidocConfig.fromProperties(openApiMap);
cfg.rapidocConfig = RapidocConfig.fromProperties(openApiMap, context);
cfg.rapidocConfig.rapiPDFConfig = rapiPDFConfig;
}
if ("true".equals(openApiMap.getOrDefault("swagger-ui.enabled", Boolean.FALSE.toString()))) {
cfg.swaggerUIConfig = SwaggerUIConfig.fromProperties(openApiMap);
cfg.swaggerUIConfig = SwaggerUIConfig.fromProperties(openApiMap, context);
cfg.swaggerUIConfig.rapiPDFConfig = rapiPDFConfig;
}
cfg.mappingPath = openApiMap.getOrDefault("mapping.path", "swagger");
Expand Down Expand Up @@ -338,7 +341,7 @@ private void render(AbstractViewConfig cfg, Path outputDir, String templateName,
}

template = cfg.render(template, context);
template = replacePlaceHolder(template, "specURL", getSpecURL(context), "");
template = replacePlaceHolder(template, "specURL", getSpecURL(cfg, context), "");
template = replacePlaceHolder(template, "title", getTitle(), "");
if (!Files.exists(outputDir)) {
Files.createDirectories(outputDir);
Expand Down Expand Up @@ -389,14 +392,20 @@ public void setTitle(String title) {
/**
* Returns the relative openApi specification url path.
*
* @param cfg view config.
* @param context Visitor context.
*
* @return A path.
*/
public String getSpecURL(VisitorContext context) {
public String getSpecURL(AbstractViewConfig cfg, VisitorContext context) {

if (cfg.specUrl != null) {
return cfg.specUrl;
}

String specUrl = StringUtils.prependUri(serverContextPath, StringUtils.prependUri(mappingPath, specFile));
if (StringUtils.isEmpty(serverContextPath)) {
String contextPath = OpenApiApplicationVisitor.getConfigurationProperty("micronaut.server.context-path", context);
String contextPath = OpenApiApplicationVisitor.getConfigurationProperty(MICRONAUT_SERVER_CONTEXT_PATH, context);
if (contextPath == null) {
contextPath = StringUtils.EMPTY_STRING;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,14 @@ private RapiPDFConfig() {
* Builds a RapiPDFConfig given a set of properties.
*
* @param properties A set of properties.
* @param context Visitor context.
*
* @return A RapipdfConfig.
*/
static RapiPDFConfig fromProperties(Map<String, String> properties) {
static RapiPDFConfig fromProperties(Map<String, String> properties, VisitorContext context) {
RapiPDFConfig cfg = new RapiPDFConfig();
cfg.enabled = "true".equals(properties.getOrDefault("rapipdf.enabled", Boolean.FALSE.toString()));
return AbstractViewConfig.fromProperties(cfg, DEFAULT_OPTIONS, properties);
return AbstractViewConfig.fromProperties(cfg, DEFAULT_OPTIONS, properties, context);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,11 +387,12 @@ private RapidocConfig() {
* Builds a RapidocConfig given a set of properties.
*
* @param properties A set of properties.
* @param context Visitor context.
*
* @return A RapidocConfig.
*/
static RapidocConfig fromProperties(Map<String, String> properties) {
return AbstractViewConfig.fromProperties(new RapidocConfig(), DEFAULT_OPTIONS, properties);
static RapidocConfig fromProperties(Map<String, String> properties, VisitorContext context) {
return AbstractViewConfig.fromProperties(new RapidocConfig(), DEFAULT_OPTIONS, properties, context);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,12 @@ private RedocConfig() {
* Builds a RedocConfig given a set of properties.
*
* @param properties A set of properties.
* @param context Visitor context.
*
* @return A RedocConfig.
*/
static RedocConfig fromProperties(Map<String, String> properties) {
return AbstractViewConfig.fromProperties(new RedocConfig(), DEFAULT_OPTIONS, properties);
static RedocConfig fromProperties(Map<String, String> properties, VisitorContext context) {
return AbstractViewConfig.fromProperties(new RedocConfig(), DEFAULT_OPTIONS, properties, context);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,11 @@ static boolean hasOauth2Option(Map<String, Object> options) {
* Builds a SwaggerUIConfig given a set of properties.
*
* @param properties A set of properties.
* @param context Visitor context.
*
* @return A SwaggerUIConfig.
*/
static SwaggerUIConfig fromProperties(Map<String, String> properties) {
static SwaggerUIConfig fromProperties(Map<String, String> properties, VisitorContext context) {
SwaggerUIConfig cfg = new SwaggerUIConfig();
cfg.theme = Theme.valueOf(properties.getOrDefault(PREFIX_SWAGGER_UI + ".theme", cfg.theme.name()).toUpperCase(Locale.US));

Expand All @@ -247,7 +248,7 @@ static SwaggerUIConfig fromProperties(Map<String, String> properties) {
cfg.isDefaultThemeUrl = false;
}

return AbstractViewConfig.fromProperties(cfg, DEFAULT_OPTIONS, properties);
return AbstractViewConfig.fromProperties(cfg, DEFAULT_OPTIONS, properties, context);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ Map<String, List<PathItem>> resolvePathItems(VisitorContext context, List<UriMat
if (!resultPath.startsWith("/") && !resultPath.startsWith("$")) {
resultPath = "/" + resultPath;
}
String contextPath = OpenApiApplicationVisitor.getConfigurationProperty("micronaut.server.context-path", context);
String contextPath = OpenApiApplicationVisitor.getConfigurationProperty(OpenApiApplicationVisitor.MICRONAUT_SERVER_CONTEXT_PATH, context);
if (StringUtils.isNotEmpty(contextPath)) {
if (!contextPath.startsWith("/") && !contextPath.startsWith("$")) {
contextPath = "/" + contextPath;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,14 @@ public class OpenApiApplicationVisitor extends AbstractOpenApiVisitor implements
*/
public static final String MICRONAUT_CONFIG_FILE_LOCATIONS = "micronaut.openapi.config.file.locations";

/**
* Loaded micronaut-http server context path property.
*/
public static final String MICRONAUT_SERVER_CONTEXT_PATH = "micronaut.server.context-path";
/**
* Final calculated openapi filename.
*/
public static final String MICRONAUT_INTERNAL_OPENAPI_FILENAME = "micronaut.internal.openapi.filename";
/**
* Loaded micronaut environment.
*/
Expand Down Expand Up @@ -873,7 +881,7 @@ private OpenAPI readOpenApi(ClassElement element, VisitorContext context) {

private void renderViews(String title, String specFile, Path destinationDir, VisitorContext context) throws IOException {
String viewSpecification = getConfigurationProperty(MICRONAUT_OPENAPI_VIEWS_SPEC, context);
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(viewSpecification, readOpenApiConfigFile(context));
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(viewSpecification, readOpenApiConfigFile(context), context);
if (cfg.isEnabled()) {
cfg.setTitle(title);
cfg.setSpecFile(specFile);
Expand Down Expand Up @@ -1197,6 +1205,8 @@ public void finish(VisitorContext context) {
context.warn("Can't set some placeholders in fileName: " + fileName, null);
}

context.put(MICRONAUT_INTERNAL_OPENAPI_FILENAME, fileName);

writeYamlToFile(openApi, fileName, documentTitle, context, isYaml);
visitedElements = visitedElements(context);
} catch (Throwable t) {
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class OpenApiOperationViewParseSpec extends Specification {
void "test parse empty OpenApiView specification"() {
given:
String spec = ""
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties())
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties(), null)

expect:
cfg.enabled == false
Expand All @@ -16,7 +16,7 @@ class OpenApiOperationViewParseSpec extends Specification {
void "test parse OpenApiView specification, views enabled"() {
given:
String spec = "mapping.path=somewhere,redoc.enabled=true,rapidoc.enabled=true,swagger-ui.enabled=true"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties())
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties(), null)

expect:
cfg.enabled == true
Expand All @@ -28,8 +28,8 @@ class OpenApiOperationViewParseSpec extends Specification {

void "test parse OpenApiView specification, redoc enabled"() {
given:
String spec = "redoc.enabled=true,redoc.js.url=version123"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties())
String spec = "redoc.enabled=true,redoc.js.url=version123,redoc.spec.url=/my/spec/file.yml"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties(), null)

expect:
cfg.enabled == true
Expand All @@ -38,12 +38,13 @@ class OpenApiOperationViewParseSpec extends Specification {
cfg.swaggerUIConfig == null
cfg.redocConfig != null
cfg.redocConfig.jsUrl == "version123"
cfg.redocConfig.specUrl == "/my/spec/file.yml"
}

void "test parse OpenApiView specification, rapidoc enabled"() {
given:
String spec = "rapidoc.enabled=true,rapidoc.js.url=version123,rapidoc.layout=row,rapidoc.theme=light"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties())
String spec = "rapidoc.enabled=true,rapidoc.js.url=version123,rapidoc.layout=row,rapidoc.theme=light,rapidoc.spec.url=/my/spec/file.yml"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties(), null)

expect:
cfg.enabled == true
Expand All @@ -52,14 +53,15 @@ class OpenApiOperationViewParseSpec extends Specification {
cfg.swaggerUIConfig == null
cfg.rapidocConfig != null
cfg.rapidocConfig.jsUrl == "version123"
cfg.rapidocConfig.specUrl == "/my/spec/file.yml"
cfg.rapidocConfig.options['theme'] == RapidocConfig.Theme.LIGHT
cfg.rapidocConfig.options['layout'] == RapidocConfig.Layout.ROW
}

void "test parse OpenApiView specification, swagger-ui enabled"() {
given:
String spec = "swagger-ui.enabled=true,swagger-ui.js.url=version123,swagger-ui.theme=flattop,swagger-ui.deepLinking=false"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties())
String spec = "swagger-ui.enabled=true,swagger-ui.js.url=version123,swagger-ui.spec.url=/my/spec/file.yml,swagger-ui.theme=flattop,swagger-ui.deepLinking=false"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties(), null)

expect:
cfg.enabled == true
Expand All @@ -68,6 +70,7 @@ class OpenApiOperationViewParseSpec extends Specification {
cfg.rapidocConfig == null
cfg.swaggerUIConfig != null
cfg.swaggerUIConfig.jsUrl == "version123"
cfg.swaggerUIConfig.specUrl == "/my/spec/file.yml"
cfg.swaggerUIConfig.theme == SwaggerUIConfig.Theme.FLATTOP
cfg.swaggerUIConfig.options['deepLinking'] == false
}
Expand Down
Loading

0 comments on commit 287773f

Please sign in to comment.