Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to set final swagger file path for UI. #1051

Merged
merged 1 commit into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -318,7 +318,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