diff --git a/build.sbt b/build.sbt index 5538ba5a..d2ece72f 100644 --- a/build.sbt +++ b/build.sbt @@ -59,6 +59,7 @@ lazy val noPublish = Seq( val elmSettings = Seq( elmCompileMode := ElmCompileMode.Debug, Compile / resourceGenerators += Def.task { + openapiCodegen.value compileElm( streams.value.log, (Compile / baseDirectory).value, @@ -565,6 +566,18 @@ val root = project // --- Helpers +def copyWithGZ(src: File, target: File): Seq[File] = { + val gzipFilter = "*.html" || "*.css" || "*.js" + IO.copy(Seq(src -> target)) + if (gzipFilter.accept(src)) { + val gz = file(target.toString + ".gz") + IO.gzip(src, gz) + Seq(target, gz) + } else { + Seq(target) + } +} + def copyWebjarResources( src: Seq[File], base: File, @@ -577,18 +590,16 @@ def copyWebjarResources( src.flatMap { dir => if (dir.isDirectory) { val files = (dir ** "*").filter(_.isFile).get.pair(Path.relativeTo(dir)) - files.map { + files.flatMap { case (f, name) => val target = targetDir / name IO.createDirectories(Seq(target.getParentFile)) - IO.copy(Seq(f -> target)) - target + copyWithGZ(f, target) } } else { val target = targetDir / dir.name IO.createDirectories(Seq(target.getParentFile)) - IO.copy(Seq(dir -> target)) - Seq(target) + copyWithGZ(dir, target) } } } @@ -611,7 +622,9 @@ def compileElm( ) val out = proc.!! logger.info(out) - Seq(target) + val targetGZ = file(target.toString + ".gz") + IO.gzip(target, targetGZ) + Seq(target, targetGZ) } def createWebjarSource(wj: Seq[ModuleID], out: File): Seq[File] = { diff --git a/modules/restserver/src/main/scala/docspell/restserver/webapp/WebjarRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/webapp/WebjarRoutes.scala index 48f03102..218855ff 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/webapp/WebjarRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/webapp/WebjarRoutes.scala @@ -1,41 +1,50 @@ package docspell.restserver.webapp +import cats.data.Kleisli +import cats.data.OptionT import cats.effect._ import org.http4s.HttpRoutes -import org.http4s.server.staticcontent.NoopCacheStrategy -import org.http4s.server.staticcontent.WebjarService.{Config => WebjarConfig, WebjarAsset} -import org.http4s.server.staticcontent.webjarService +import org.http4s.Method +import org.http4s.Response +import org.http4s.StaticFile object WebjarRoutes { + private[this] val suffixes = List( + ".js", + ".css", + ".html", + ".json", + ".jpg", + ".png", + ".eot", + ".woff", + ".woff2", + ".svg", + ".otf", + ".ttf", + ".yml", + ".xml" + ) + def appRoutes[F[_]: Effect]( blocker: Blocker - )(implicit C: ContextShift[F]): HttpRoutes[F] = - webjarService( - WebjarConfig( - filter = assetFilter, - blocker = blocker, - cacheStrategy = NoopCacheStrategy[F] - ) - ) - - def assetFilter(asset: WebjarAsset): Boolean = - List( - ".js", - ".css", - ".html", - ".json", - ".jpg", - ".png", - ".eot", - ".woff", - ".woff2", - ".svg", - ".otf", - ".ttf", - ".yml", - ".xml" - ).exists(e => asset.asset.endsWith(e)) + )(implicit CS: ContextShift[F]): HttpRoutes[F] = + Kleisli { + case req if req.method == Method.GET => + val p = req.pathInfo + if (p.contains("..") || !suffixes.exists(p.endsWith(_))) + OptionT.pure(Response.notFound[F]) + else + StaticFile.fromResource( + s"/META-INF/resources/webjars$p", + blocker, + Some(req), + true + ) + case _ => + OptionT.none + } }