ApiPathFilter.java
package de.dlr.shepard.filters;
import io.quarkus.smallrye.openapi.OpenApiFilter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.microprofile.openapi.OASFactory;
import org.eclipse.microprofile.openapi.OASFilter;
import org.eclipse.microprofile.openapi.models.OpenAPI;
import org.eclipse.microprofile.openapi.models.PathItem;
import org.eclipse.microprofile.openapi.models.Paths;
import org.eclipse.microprofile.openapi.models.media.Schema;
@OpenApiFilter(OpenApiFilter.RunStage.BUILD)
public class ApiPathFilter implements OASFilter {
@Override
public void filterOpenAPI(OpenAPI openAPI) {
fixOpenApiPaths(openAPI);
excludeExtraHealthEndpointsAndAdjustHealthzTag(openAPI);
sortPropertiesOfHealthCheckSchemas(openAPI);
}
/**
* Remove the quarkus-injected '/shepard/api' path part from the OpenApi paths
* <p>
* The deployment goal is to have the /shepard/api as part of the base path,
* but not as part of the actual endpoint path. So this part is removed.
*
*/
private void fixOpenApiPaths(OpenAPI openAPI) {
Paths newPaths = OASFactory.createPaths();
Map<String, PathItem> paths = openAPI.getPaths().getPathItems();
for (var entry : paths.entrySet()) {
// modify i.e. /shepard/api/collections -> /collections
String modifiedPath = entry.getKey().replace("/shepard/api", "");
newPaths.addPathItem(modifiedPath, entry.getValue());
}
openAPI.setPaths(newPaths);
}
/**
* Clean the health check endpoints in OpenAPI documentation.
*/
private void excludeExtraHealthEndpointsAndAdjustHealthzTag(OpenAPI openAPI) {
Paths newPaths = OASFactory.createPaths();
Map<String, PathItem> paths = openAPI.getPaths().getPathItems();
newPaths.setPathItems(
paths
.entrySet()
.stream()
.filter(path -> !List.of("/healthz/ready", "/healthz/live", "/healthz/started").contains(path.getKey()))
.map(path -> {
if (
path.getValue().getGET() == null || !path.getValue().getGET().getTags().contains("MicroProfile Health")
) return path;
PathItem newPathItem = path.getValue();
newPathItem.getGET().setTags(List.of("healthz"));
newPathItem.getGET().setOperationId("getServerHealth");
return Map.entry(path.getKey(), newPathItem);
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
);
openAPI.setPaths(newPaths);
}
private void sortPropertiesOfHealthCheckSchemas(OpenAPI openAPI) {
Map<String, Schema> schemas = openAPI.getComponents().getSchemas();
openAPI
.getComponents()
.setSchemas(
schemas
.entrySet()
.stream()
.map(schema -> {
if (!List.of("HealthCheck", "HealthResponse").contains(schema.getKey())) {
return schema;
}
schema
.getValue()
.setProperties(
schema
.getValue()
.getProperties()
.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.collect(
Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(oldValue, newValue) -> oldValue,
LinkedHashMap::new
)
)
);
return schema;
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
);
}
}