scala-cask.openapiRoute.mustache Maven / Gradle / Ivy
{{>licenseInfo}}
// generated from openapiRoute.mustache
package {{apiPackage}}
import cask.model.Response
import java.nio.file.{Files, Path, Paths}
/**
* This code will try and download the swagger UI static files on startup
*
* That behaviour can be altered by:
* - setting the environment variable SWAGGER_ON to false
* - setting the environment variable SWAGGER_UI_URL to either the URL of a swagger UI zip or setting it to the empty string
*
*/
object OpenApiRoutes {
def swaggerUIUrl: Option[String] = {
// flag to turn SWAGGER off
def useSwaggerUI = sys.env.get("SWAGGER_ON").map(_.toBoolean).getOrElse(true)
val defaultUrl = "https://github.com/swagger-api/swagger-ui/archive/refs/tags/v5.11.9.zip"
Option(sys.env.getOrElse("SWAGGER_UI_URL", defaultUrl))
.map(_.trim)
.filterNot(_.isEmpty)
.filter(_ => useSwaggerUI)
}
def apply(localPort: Int) = new OpenApiRoutes(localPort, swaggerUIUrl)
}
class OpenApiRoutes(localPort: Int, swaggerUrl: Option[String]) extends cask.Routes {
def openApiDir = "ui"
@cask.get("/")
def index() = cask.Redirect("/ui/index.html")
@cask.staticFiles("/ui")
def staticUI() = openApiDir
@cask.staticResources("/openapi.json")
def staticOpenApi() = "openapi.json"
/** This code will try and download the swagger UI artefacts to a local directory to serve up
*/
object extract {
def openApiDirPath: Path = Paths.get(openApiDir)
def hasSwagger = Files.exists(openApiDirPath) && Files.isDirectory(openApiDirPath)
import java.io.{BufferedInputStream, FileOutputStream, InputStream}
import java.net.URL
import java.util.zip.{ZipEntry, ZipInputStream}
import scala.util.Using
def apply(url: String) = {
if !hasSwagger then downloadAndExtractZip(url, openApiDir)
}
def downloadAndExtractZip(url: String, outputDir: String): Unit = {
val urlConn = new URL(url).openConnection()
urlConn.setRequestProperty("User-Agent", "Mozilla/5.0")
Using(urlConn.getInputStream) { inputStream =>
val zipIn = new ZipInputStream(new BufferedInputStream(inputStream))
LazyList.continually(zipIn.getNextEntry).takeWhile(_ != null).foreach { entry =>
def isDist = entry.getName.contains("/dist/")
def isNotMap = !entry.getName.endsWith(".map")
if (!entry.isDirectory && isDist && isNotMap) {
val fileName = entry.getName.split("/").last
extractFile(entry.getName, zipIn, s"$outputDir/$fileName")
}
zipIn.closeEntry()
}
}
}
def extractFile(name: String, zipIn: ZipInputStream, filePath: String): Unit = {
val fullPath = Paths.get(filePath).toAbsolutePath
if !Files.exists(fullPath.getParent) then {
Files.createDirectories(fullPath.getParent)
}
// config hack - we replace the default url from this swagger conf to use our localhost
//
if name.endsWith("swagger-initializer.js") then {
val textLines = scala.io.Source.fromInputStream(zipIn).getLines().map {
case line if line.contains("url:") =>
s""" url: "http://localhost:$localPort/openapi.json","""
case line => line
}
// keeping this compatible for java 8, where this is from >= java 11:
// Files.writeString(fullPath, textLines.mkString("\n"))
scala.util.Using(new java.io.PrintWriter(fullPath.toFile))(_.write(textLines.mkString("\n")))
} else {
Using(new FileOutputStream(filePath)) { outputStream =>
val buffer = new Array[Byte](1024)
LazyList
.continually(zipIn.read(buffer))
.takeWhile(_ != -1)
.foreach(outputStream.write(buffer, 0, _))
}
}
}
}
// extract the swagger UI resources to our local directory
swaggerUrl.foreach(url => extract(url))
initialize()
}