feat(01): Simple initial landing
This commit is contained in:
@@ -10,15 +10,18 @@ object Main extends ZIOAppDefault {
|
||||
|
||||
private val banner: String =
|
||||
"""
|
||||
| .
|
||||
| \ | /
|
||||
| '-.ooooo.-'
|
||||
| --- ooooo ---
|
||||
| .-'ooooo'-.
|
||||
| / | \
|
||||
| '
|
||||
|
|
||||
| S U M M E R C M S
|
||||
| | .
|
||||
| `. * | .'
|
||||
| `. ._|_* .' .
|
||||
| . * .' `. *
|
||||
| -------| |-------
|
||||
| . *`.___.' * .
|
||||
| .' |* `. *
|
||||
| .' * | . `.
|
||||
| . |
|
||||
|
|
||||
| S U M M E R C M S
|
||||
|""".stripMargin
|
||||
|
||||
override val bootstrap: ZLayer[ZIOAppArgs, Any, Any] =
|
||||
@@ -28,7 +31,7 @@ object Main extends ZIOAppDefault {
|
||||
for {
|
||||
cfg <- ZIO.config[SummerConfig](SummerConfig.config)
|
||||
_ <- Console.printLine(banner)
|
||||
_ <- Console.printLine(s" Starting on port ${cfg.server.port}...")
|
||||
_ <- Console.printLine(s"Starting on port ${cfg.server.port}...")
|
||||
_ <- Console.printLine("")
|
||||
// Note: Migrations are NOT auto-run. Use CLI to run migrations (Phase 5).
|
||||
_ <- Server.serve(Routes.routes).provide(
|
||||
|
||||
62
summercms/src/api/LandingRoutes.scala
Normal file
62
summercms/src/api/LandingRoutes.scala
Normal file
@@ -0,0 +1,62 @@
|
||||
package api
|
||||
|
||||
import zio.*
|
||||
import zio.http.*
|
||||
import scala.io.Source
|
||||
|
||||
/** Landing page and static asset routes
|
||||
*/
|
||||
object LandingRoutes {
|
||||
|
||||
private def loadResource(path: String): Option[String] =
|
||||
Option(getClass.getClassLoader.getResourceAsStream(path)).map { stream =>
|
||||
val content = Source.fromInputStream(stream, "UTF-8").mkString
|
||||
stream.close()
|
||||
content
|
||||
}
|
||||
|
||||
private def serveLanding: ZIO[Any, Nothing, Response] =
|
||||
ZIO.succeed {
|
||||
loadResource("public/landing.html") match {
|
||||
case Some(html) =>
|
||||
Response(
|
||||
status = Status.Ok,
|
||||
headers = Headers(Header.ContentType(MediaType.text.html)),
|
||||
body = Body.fromString(html)
|
||||
)
|
||||
case None =>
|
||||
Response.text("Landing page not found").status(Status.InternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
private def serveImage(filename: String): ZIO[Any, Nothing, Response] =
|
||||
ZIO.attemptBlocking {
|
||||
val path = s"public/assets/images/$filename"
|
||||
val stream = getClass.getClassLoader.getResourceAsStream(path)
|
||||
if (stream == null) {
|
||||
Response.notFound
|
||||
} else {
|
||||
val bytes = stream.readAllBytes()
|
||||
stream.close()
|
||||
val mediaType = if (filename.endsWith(".png")) MediaType.image.png
|
||||
else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) MediaType.image.jpeg
|
||||
else if (filename.endsWith(".svg")) MediaType.image.`svg+xml`
|
||||
else if (filename.endsWith(".gif")) MediaType.image.gif
|
||||
else MediaType.application.`octet-stream`
|
||||
Response(
|
||||
status = Status.Ok,
|
||||
headers = Headers(Header.ContentType(mediaType)),
|
||||
body = Body.fromChunk(Chunk.fromArray(bytes))
|
||||
)
|
||||
}
|
||||
}.catchAll(_ => ZIO.succeed(Response.notFound))
|
||||
|
||||
val routes: Routes[Any, Response] =
|
||||
Routes(
|
||||
Method.GET / Root -> handler(serveLanding),
|
||||
Method.GET / "assets" / "images" / string("filename") -> handler { (filename: String, _: Request) =>
|
||||
serveImage(filename)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
@@ -10,6 +10,6 @@ import javax.sql.DataSource
|
||||
object Routes {
|
||||
|
||||
val routes: Routes[DataSource, Response] =
|
||||
HealthRoutes.routes
|
||||
LandingRoutes.routes ++ HealthRoutes.routes
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user