diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerUIController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerUIController.java new file mode 100644 index 0000000000000000000000000000000000000000..ed29297569a60db42f9c20de679747697ef95e24 --- /dev/null +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerUIController.java @@ -0,0 +1,120 @@ +package gov.usgs.earthquake.nshmp.www; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Optional; + +import org.apache.commons.io.IOUtils; + +import io.micronaut.core.io.scan.ClassPathResourceLoader; +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Produces; +import io.swagger.v3.oas.annotations.Hidden; +import jakarta.annotation.Nullable; +import jakarta.inject.Inject; + +/** + * Handle Swagger static resources. + */ +@Controller( + value = "${nshmp.context-path}/", + produces = { + MediaType.APPLICATION_YAML, + MediaType.TEXT_HTML, + MediaType.IMAGE_PNG, + MediaType.TEXT_PLAIN, + "font/woff", + "font/woff2", + "font/ttf", + "image/svg+xml", + "text/css", + "text/javascript", + }) +public class SwaggerUIController { + private static final String SWAGGER_UI_RESOURCE_LOCATION = "classpath:swagger/"; + private final ClassPathResourceLoader loader; + + public SwaggerUIController(ClassPathResourceLoader loader) { + this.loader = loader; + } + + @Inject + private NshmpMicronautServlet servlet; + + @Get("{/path:.*}{.ext:png}") + @Produces("image/png; charset=utf-8") + @Hidden + public byte[] getSwaggerPngImages( + @PathVariable @Nullable String path, + @PathVariable @Nullable String ext) throws IOException { + Optional<URL> resource = loader.getResource(SWAGGER_UI_RESOURCE_LOCATION + path + "." + ext); + return IOUtils.toByteArray(resource.orElseThrow().openStream()); + } + + @Get("{/path:.*}{.ext:b64}") + @Produces(MediaType.TEXT_PLAIN) + @Hidden + public HttpResponse<String> getSwaggerBase64Images( + @PathVariable @Nullable String path, + @PathVariable @Nullable String ext) throws IOException { + return HttpResponse.ok(getResourceString(SWAGGER_UI_RESOURCE_LOCATION + path + "." + ext)) + .contentType(MediaType.TEXT_PLAIN); + } + + @Get("{/path:.*}{.ext:css|js}") + @Produces({ "text/css", "text/javascript" }) + @Hidden + public String getSwaggerLibrary( + @PathVariable @Nullable String path, + @PathVariable @Nullable String ext) throws IOException { + return getResourceString(SWAGGER_UI_RESOURCE_LOCATION + path + "." + ext); + } + + @Get("{/path:.*}{.ext:svg}") + @Produces("image/svg+xml") + @Hidden + public String getSwaggerSvgImages( + @PathVariable @Nullable String path, + @PathVariable @Nullable String ext) throws IOException { + return getResourceString(SWAGGER_UI_RESOURCE_LOCATION + path + "." + ext); + } + + @Get("{/path:.*}{.ext:eot}") + @Produces("application/vnd.ms-fontobject") + @Hidden + public String getSwaggerEotFont( + @PathVariable @Nullable String path, + @PathVariable @Nullable String ext) throws IOException { + return getResourceString(SWAGGER_UI_RESOURCE_LOCATION + path + "." + ext); + } + + @Get("{/path:.*}{.ext:woff|woff2|ttf|otf}") + @Produces("font/*") + @Hidden + public String getSwaggerFont( + @PathVariable @Nullable String path, + @PathVariable @Nullable String ext) throws IOException { + return getResourceString(SWAGGER_UI_RESOURCE_LOCATION + path + "." + ext); + } + + @Get("/") + @Produces(MediaType.TEXT_HTML) + @Hidden + public String getSwaggerIndexPage() throws IOException { + return getResourceString("classpath:swagger/index.html"); + } + + private String getResourceString(String path) throws IOException { + Optional<URL> resource = loader.getResource(path); + + return IOUtils.toString( + (BufferedInputStream) resource.orElseThrow().getContent(), + StandardCharsets.UTF_8); + } +}