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

Append micronaut.server.context-path to endpoints #1775

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.core.util.StringUtils;
import io.micronaut.inject.visitor.VisitorContext;
import io.micronaut.openapi.visitor.ConfigUtils;
import io.micronaut.openapi.visitor.ContextUtils;
import io.micronaut.openapi.visitor.Pair;
import io.micronaut.openapi.visitor.group.OpenApiInfo;
Expand All @@ -43,13 +44,13 @@
import java.util.Optional;
import java.util.Properties;

import static io.micronaut.openapi.visitor.ConfigUtils.getConfigProperty;
import static io.micronaut.openapi.visitor.ConfigUtils.getProjectPath;
import static io.micronaut.openapi.visitor.ContextUtils.addGeneratedResource;
import static io.micronaut.openapi.visitor.ContextUtils.info;
import static io.micronaut.openapi.visitor.ContextUtils.warn;
import static io.micronaut.openapi.visitor.FileUtils.readFile;
import static io.micronaut.openapi.visitor.FileUtils.resolve;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH;
import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_SERVER_CONTEXT_PATH;
import static io.micronaut.openapi.visitor.StringUtil.COMMA;
import static io.micronaut.openapi.visitor.StringUtil.DOLLAR;
Expand Down Expand Up @@ -88,7 +89,6 @@ public final class OpenApiViewConfig {
private String mappingPath;
private String title;
private String specFile;
private String serverContextPath = StringUtils.EMPTY_STRING;
private SwaggerUIConfig swaggerUIConfig;
private RedocConfig redocConfig;
private RapidocConfig rapidocConfig;
Expand Down Expand Up @@ -390,15 +390,6 @@ private void render(AbstractViewConfig cfg, Path outputDir, String templateName,
}
}

/**
* Sets the server context path.
*
* @param contextPath The server context path.
*/
public void setServerContextPath(String contextPath) {
serverContextPath = contextPath == null ? StringUtils.EMPTY_STRING : contextPath;
}

/**
* Returns the title for the generated views.
*
Expand Down Expand Up @@ -434,26 +425,31 @@ public String getSpecURL(AbstractViewConfig cfg, @Nullable VisitorContext contex
return StringUtils.EMPTY_STRING;
}

String specUrl = StringUtils.prependUri(serverContextPath, StringUtils.prependUri(mappingPath, specFile));
if (StringUtils.isEmpty(serverContextPath)) {
String contextPath = getConfigProperty(MICRONAUT_SERVER_CONTEXT_PATH, context);
if (contextPath == null) {
contextPath = StringUtils.EMPTY_STRING;
}
if (!contextPath.startsWith(SLASH) && !contextPath.startsWith(DOLLAR)) {
contextPath = SLASH + contextPath;
}
if (!contextPath.endsWith(SLASH)) {
contextPath += SLASH;
}
if (specUrl.startsWith(SLASH)) {
specUrl = specUrl.substring(1);
}
// process micronaut.openapi.server.context.path
String serverContextPath = ConfigUtils.getConfigProperty(MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH, context);
if (serverContextPath == null) {
serverContextPath = StringUtils.EMPTY_STRING;
}
String finalUrl = serverContextPath.startsWith(SLASH) ? serverContextPath : SLASH + serverContextPath;
if (!finalUrl.endsWith(SLASH)) {
finalUrl += SLASH;
}

specUrl = contextPath + specUrl;
// process micronaut.server.context-path
String contextPath = ConfigUtils.getConfigProperty(MICRONAUT_SERVER_CONTEXT_PATH, context);
if (contextPath == null) {
contextPath = StringUtils.EMPTY_STRING;
}
finalUrl += contextPath.startsWith(SLASH) ? contextPath.substring(1) : contextPath;
if (!finalUrl.endsWith(SLASH)) {
finalUrl += SLASH;
}

return specUrl;
finalUrl = StringUtils.prependUri(finalUrl, StringUtils.prependUri(mappingPath, specFile));
if (!finalUrl.startsWith(SLASH) && !finalUrl.startsWith(DOLLAR)) {
finalUrl = SLASH + finalUrl;
}
return finalUrl;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ Map<String, List<PathItem>> resolvePathItems(VisitorContext context, List<UriMat
var resultPathItemsMap = new HashMap<String, List<PathItem>>();

for (UriMatchTemplate matchTemplate : matchTemplates) {
var segms = parsePathSegments(matchTemplate.toPathString());
var finalPaths = buildUrls(segms);
var segments = parsePathSegments(matchTemplate.toPathString());
var finalPaths = buildUrls(segments, context);

for (String finalPath : finalPaths) {
List<PathItem> resultPathItems = resultPathItemsMap.computeIfAbsent(finalPath, k -> new ArrayList<>());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ private void renderViews(String title, Map<Pair<String, String>, OpenApiInfo> op
if (CollectionUtils.isNotEmpty(openApiInfos)) {
cfg.setSpecFile(openApiInfos.values().iterator().next().getSpecFilePath());
}
cfg.setServerContextPath(getConfigProperty(MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH, context));
cfg.render(destinationDir, context);
}
}
Expand Down
20 changes: 19 additions & 1 deletion openapi/src/main/java/io/micronaut/openapi/visitor/UrlUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@
package io.micronaut.openapi.visitor;

import io.micronaut.core.annotation.Internal;
import io.micronaut.core.util.StringUtils;
import io.micronaut.inject.visitor.VisitorContext;

import java.util.ArrayList;
import java.util.List;

import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_SERVER_CONTEXT_PATH;
import static io.micronaut.openapi.visitor.StringUtil.CLOSE_BRACE;
import static io.micronaut.openapi.visitor.StringUtil.DOLLAR;
import static io.micronaut.openapi.visitor.StringUtil.OPEN_BRACE;
Expand Down Expand Up @@ -47,7 +50,7 @@ private UrlUtils() {
* @param segments url template segments
* @return all possible URL variants by parsed segments.
*/
public static List<String> buildUrls(List<Segment> segments) {
public static List<String> buildUrls(List<Segment> segments, VisitorContext context) {

var results = new ArrayList<StringBuilder>();

Expand All @@ -57,6 +60,16 @@ public static List<String> buildUrls(List<Segment> segments) {
prevSegment = segment;
}

String contextPath = ConfigUtils.getConfigProperty(MICRONAUT_SERVER_CONTEXT_PATH, context);
if (StringUtils.isNotEmpty(contextPath)) {
if (!contextPath.startsWith(SLASH) && !contextPath.startsWith(DOLLAR)) {
contextPath = SLASH + contextPath;
}
if (contextPath.endsWith(SLASH)) {
contextPath = contextPath.substring(0, contextPath.length() - 1);
}
}

var resultStrings = new ArrayList<String>();
for (var res : results) {
var url = res.toString();
Expand All @@ -67,6 +80,11 @@ public static List<String> buildUrls(List<Segment> segments) {
} else if (url.startsWith(SLASH + DOLLAR)) {
url = url.substring(1);
}

if (StringUtils.isNotEmpty(contextPath)) {
url = contextPath + url;
}

if (!resultStrings.contains(url)) {
resultStrings.add(url);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import spock.util.environment.RestoreSystemProperties

class OpenApiOperationViewRenderSpec extends Specification {
def cleanup() {
Expand Down Expand Up @@ -168,14 +169,15 @@ class OpenApiOperationViewRenderSpec extends Specification {
outputDir.resolve("swagger-ui").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains("link(contextPath + \"https://flattop.com/theme.css\", head, \"text/css\", \"stylesheet\")")
}

@RestoreSystemProperties
void "test render OpenApiView specification with server context path"() {
given:
System.setProperty(OpenApiConfigProperty.MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH, "/context-path")
String spec = "redoc.enabled=true,rapidoc.enabled=true,swagger-ui.enabled=true,openapi-explorer.enabled=true"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, null, new Properties(), null)
Path outputDir = Paths.get("output")
cfg.title = "OpenAPI documentation"
cfg.specFile = "swagger.yml"
cfg.serverContextPath = "/context-path"
cfg.render(outputDir, null)

expect:
Expand Down Expand Up @@ -233,14 +235,15 @@ class OpenApiOperationViewRenderSpec extends Specification {
outputDir.resolve("openapi-explorer").resolve("index.html").toFile().getText(StandardCharsets.UTF_8.name()).contains(cfg.getSpecURL(cfg.openApiExplorerConfig, null))
}

@RestoreSystemProperties
void "test render OpenApiView specification with custom mapping path and server context path"() {
given:
System.setProperty(OpenApiConfigProperty.MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH, "/context-path")
String spec = "mapping.path=somewhere,redoc.enabled=true,rapidoc.enabled=true,swagger-ui.enabled=true,openapi-explorer.enabled=true"
OpenApiViewConfig cfg = OpenApiViewConfig.fromSpecification(spec, null, new Properties(), null)
Path outputDir = Paths.get("output")
cfg.title = "OpenAPI documentation"
cfg.specFile = "swagger.yml"
cfg.serverContextPath = "/context-path"
cfg.render(outputDir, null)

expect:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.swagger.v3.oas.models.PathItem
import io.swagger.v3.oas.models.Paths
import io.swagger.v3.oas.models.media.Schema
import spock.lang.Issue
import spock.util.environment.RestoreSystemProperties

class OpenApiControllerVisitorSpec extends AbstractOpenApiTypeElementSpec {

Expand Down Expand Up @@ -2459,4 +2460,41 @@ class MyBean {}
operation.requestBody.content."application/json".schema
operation.requestBody.content."application/json".schema.$ref == "#/components/schemas/SimpleBody"
}

@RestoreSystemProperties
void "test append micronaut.server.context-path to endpoints"() {
given:
System.setProperty(OpenApiConfigProperty.MICRONAUT_SERVER_CONTEXT_PATH, "/local-path")
System.setProperty(OpenApiConfigProperty.MICRONAUT_OPENAPI_CONTEXT_SERVER_PATH, "/server-context-path")

buildBeanDefinition('test.MyBean', '''
package test;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import jakarta.inject.Singleton;

@Controller("/test")
class TestController {

@Get("/save{/id}")
String save() {
return null;
}
}

@Singleton
class MyBean {}
''')
when:
OpenAPI openAPI = Utils.testReference
def paths = openAPI.paths

then:
paths
paths."/server-context-path/local-path/test/save"
paths."/server-context-path/local-path/test/save".get
paths."/server-context-path/local-path/test/save/{id}"
paths."/server-context-path/local-path/test/save/{id}".get
}
}
Loading