Skip to content

Commit

Permalink
Add ability to set final swagger file path for UI.
Browse files Browse the repository at this point in the history
Upgrade libs.
Swagger UI 4.19.0
  • Loading branch information
altro3 committed Jun 10, 2023
1 parent 2184707 commit ec68710
Show file tree
Hide file tree
Showing 19 changed files with 80 additions and 35 deletions.
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.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 @@ -28,7 +28,7 @@ class OpenApiOperationViewParseSpec extends Specification {

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

expect:
Expand All @@ -38,11 +38,12 @@ 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"
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())

expect:
Expand All @@ -52,13 +53,14 @@ 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"
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())

expect:
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
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ class OpenApiOperationViewRenderSpec extends Specification {

void "test generates urlResourcesPrefix context-path and openapi.context.path"() {
given:
System.setProperty("micronaut.server.context-path", "/local-path")
System.setProperty(OpenApiApplicationVisitor.MICRONAUT_SERVER_CONTEXT_PATH, "/local-path")
System.setProperty(OpenApiApplicationVisitor.MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH, "/server-context-path")
String spec = "swagger-ui.enabled=true"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, new Properties())
Expand All @@ -256,7 +256,7 @@ class OpenApiOperationViewRenderSpec extends Specification {
urlPrefix == '/server-context-path/local-path/swagger-ui/res/'

cleanup:
System.clearProperty("micronaut.server.context-path")
System.clearProperty(OpenApiApplicationVisitor.MICRONAUT_SERVER_CONTEXT_PATH)
System.clearProperty(OpenApiApplicationVisitor.MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH)
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/docs/guide/openApiViews/rapidoc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ The views will be generated to the `META-INF/swagger/views/rapidoc` directory of

|===
| `rapidoc.enabled` | `true` or `false` When 'true' the RapiDoc view is generated.
| `rapidoc.js.url` | Override path to use to find the js file. Path must contain a file named rapidoc-min.js. The value can be a URL path like: "https://unpkg.com/rapidoc/dist/". Must contain trailing slash.,
| `rapidoc.js.url` | Override path to use to find the js file. Path must contain a file named rapidoc-min.js. The value can be a URL path like: "https://unpkg.com/rapidoc/dist/". Must contain trailing slash.
| `rapidoc.spec.url` | Override path in swagger file path line. If you don't set, then value will be `<context-path>/swagger/<spec_filename>`. You can use the placeholder `${filename}` it will be replaced with the final name of the generated swagger file.
| `rapidoc.copy-resources` | Copy or not local JS and CSS resources. Set to `false` if you are using external resources (eg https://unpkg.com/rapidoc/dist/). Default `true`
| `rapidoc.style` |
| `rapidoc.sort-tags` |
Expand Down
1 change: 1 addition & 0 deletions src/main/docs/guide/openApiViews/rapipdf.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ RapiPdf supports the following options:
|===
| `rapipdf.enabled` | `true` or `false`,
| `rapipdf.js.url` | Override path to use to find the js file. Path must contain a file named rapdipdf-min.js. The value can be a URL path like: "https://unpkg.com/rapipdf/dist/". Must contain trailing slash.,
| `rapipdf.spec.url` | Override path in swagger file path line. If you don't set, then value will be `<context-path>/swagger/<spec_filename>`. You can use the placeholder `${filename}` it will be replaced with the final name of the generated swagger file.
| `rapipdf.copy-resources` | Copy or not local JS and CSS resources. Set to `false` if you are using external resources (eg https://unpkg.com/rapipdf/dist/). Default `true`
| `rapipdf.include-api-details`
| `rapipdf.pdf-title`
Expand Down
3 changes: 2 additions & 1 deletion src/main/docs/guide/openApiViews/redoc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ Views supports https://github.com/Rebilly/ReDoc[Redoc], to enable it use `redoc.
The views will be generated to the `META-INF/swagger/views/redoc` directory of your project’s class output.

|===
|`redoc.enabled` | `true` or `false` When 'true' the Redoc view is generated.
| `redoc.enabled` | `true` or `false` When 'true' the Redoc view is generated.
| `redoc.js.url` | Override path to use to find the js file. Path must contain a file named redoc.standalone.js. The value can be a URL path like: "https://unpkg.com/redoc/bundles/". Must contain trailing slash.,
| `redoc.spec.url` | Override path in swagger file path line. If you don't set, then value will be `<context-path>/swagger/<spec_filename>`. You can use the placeholder `${filename}` it will be replaced with the final name of the generated swagger file.
| `redoc.copy-resources` | Copy or not local JS and CSS resources. Set to `false` if you are using external resources (eg https://unpkg.com/redoc/bundles/). Default `true`
| `redoc.expand-single-schema-field` |
| `redoc.expand-default-server-variables` |
Expand Down
1 change: 1 addition & 0 deletions src/main/docs/guide/openApiViews/swaggerui.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The views will be generated to the `META-INF/swagger/views/swagger-ui` directory
|===
| `swagger-ui.enabled` | `true` or `false` When 'true' the Swagger-ui view is generated.
| `swagger-ui.js.url` | Override path to use to find the js file. Path must contain a files named swagger-ui.css, swagger-ui-bundle.js, swagger-ui-standalone-present.js. The value can be a URL path like: "https://unpkg.com/swagger-ui-dist/". Must contain trailing slash.,
| `swagger-ui.spec.url` | Override path in swagger file path line. If you don't set, then value will be `<context-path>/swagger/<spec_filename>`. You can use the placeholder `${filename}` it will be replaced with the final name of the generated swagger file.
| `swagger-ui.copy-resources` | Copy or not local JS and CSS resources. Set to `false` if you are using external resources (eg https://unpkg.com/swagger-ui-dist/). Default `true`
| `swagger-ui.theme` | `DEFAULT` or `MATERIAL` or `FEELING_BLUE` `FLATTOP` `MONOKAI` `MUTED` `NEWSPAPER` `OUTLINE`. The theme of swagger-ui to use. These are case-insensitive. Default is `DEFAULT`. See https://github.com/ostranme/swagger-ui-themes[Swagger UI Themes].
| `swagger-ui.theme.url` | Override path to use to find the theme CSS file.,
Expand Down
Loading

0 comments on commit ec68710

Please sign in to comment.