Created
May 8, 2023 13:06
-
-
Save calvinlfer/896ed9aadb313526c1ae8301dd67480c to your computer and use it in GitHub Desktop.
ZIO HTTP (Graal Native Image & Scala CLI)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
scala-cli --power package --native-image -f *.scala -o ziohttp.bin -- --no-fallback --enable-url-protocols=http,https -Djdk.http.auth.tunneling.disabledSchemes= --install-exit-handlers --enable-http --initialize-at-run-time=io.netty.channel.DefaultFileRegion --initialize-at-run-time=io.netty.channel.epoll.Native --initialize-at-run-time=io.netty.channel.epoll.Epoll --initialize-at-run-time=io.netty.channel.epoll.EpollEventLoop --initialize-at-run-time=io.netty.channel.epoll.EpollEventArray --initialize-at-run-time=io.netty.channel.kqueue.KQueue --initialize-at-run-time=io.netty.channel.kqueue.KQueueEventLoop --initialize-at-run-time=io.netty.channel.kqueue.KQueueEventArray --initialize-at-run-time=io.netty.channel.kqueue.Native --initialize-at-run-time=io.netty.channel.unix.Limits --initialize-at-run-time=io.netty.channel.unix.Errors --initialize-at-run-time=io.netty.channel.unix.IovArray --initialize-at-run-time=io.netty.handler.codec.compression.ZstdOptions --initialize-at-run-time=io.netty.incubator.channel.uring.IOUringEventLoopGroup --initialize-at-run-time=io.netty.incubator.channel.uring.Native --initialize-at-run-time=io.netty.handler.ssl.BouncyCastleAlpnSslUtils |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//> using scala "3.2.2" | |
//> using lib "dev.zio::zio:2.0.13" | |
//> using lib "dev.zio::zio-test:2.0.13" | |
//> using lib "dev.zio::zio-test-sbt:2.0.13" | |
//> using lib "dev.zio::zio-http:3.0.0-RC1" | |
//> using file "ziohttp.scala" | |
//> using mainClass "ZioHttpApp" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
scala-cli run . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import zio.* | |
import zio.http.* | |
import zio.http.internal.middlewares.Cors.* | |
import zio.http.Header.AccessControlAllowOrigin | |
import zio.http.Path.Segment | |
object ZioHttpApp extends ZIOAppDefault: | |
val PORT = 8080 | |
// Create CORS configuration | |
val corsConfig = CorsConfig( | |
allowedOrigin = _ => Some(AccessControlAllowOrigin.All), | |
allowedMethods = Header.AccessControlAllowMethods.All | |
) | |
// Add route managers and middleware | |
val httpProg = HomeApp() ++ GreetingApp() | |
@@ HttpAppMiddleware.cors(corsConfig) | |
@@ HttpAppMiddleware.debug | |
// Server config | |
val config = Server.Config.default.port(PORT) | |
val server = | |
Server.serve(httpProg).provide(ZLayer.succeed(config), Server.live) | |
val console = | |
Console.printLine(s"Server starting on http://localhost:${PORT}") | |
def run = console *> server | |
object HomeApp: | |
def apply(): Http[Any, Nothing, Request, Response] = | |
Http.collect[Request] { | |
// GET /, redirect to /greet | |
case Method.GET -> !! => | |
Response.redirect(URL(Path.decode("/greet"))) | |
} | |
object GreetingApp: | |
def apply(): Http[Any, Nothing, Request, Response] = | |
Http.collect[Request] { | |
// GET /greet?name=:name | |
case req @ (Method.GET -> !! / "greet") if req.url.queryParams.nonEmpty => | |
Response.text( | |
s"Hello ${req.url.queryParams.getOrElse("name", List("User")).mkString(" and ")}!" | |
) | |
// GET /greet/:name | |
case Method.GET -> !! / "greet" / name => | |
Response.text(s"Hello $name!") | |
// GET /greet | |
case Method.GET -> !! / "greet" => | |
Response.text("Hello World!") | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import zio.http.* | |
import zio.test.* | |
import zio.http.Header.Location | |
object MainSpec extends ZIOSpecDefault: | |
val homeApp = HomeApp() | |
val greetApp = GreetingApp() | |
def spec = | |
suite("App Tests")( | |
suite("Main backend application")( | |
test("should show start message") { | |
for | |
_ <- ZioHttpApp.console | |
output <- TestConsole.output | |
yield assertTrue(output.head contains "starting") | |
}, | |
test("root route should redirect to /greet") { | |
for | |
response <- homeApp.runZIO(Request.get(URL(!!))) | |
body <- response.body.asString | |
yield assertTrue( | |
response.status == Status.TemporaryRedirect, | |
response.headers.size == 1, | |
response.headers.head == Location(URL(!! / "greet")), | |
body.isEmpty | |
) | |
} | |
), | |
suite("Greet backend application")( | |
test("should greet world") { | |
for | |
response <- greetApp.runZIO(Request.get(URL(!! / "greet"))) | |
body <- response.body.asString | |
yield assertTrue( | |
response.status == Status.Ok, | |
body == "Hello World!" | |
) | |
}, | |
test("should greet User if using path") { | |
for | |
response <- greetApp.runZIO(Request.get(URL(!! / "greet" / "User"))) | |
body <- response.body.asString | |
yield assertTrue( | |
response.status == Status.Ok, | |
body == "Hello User!" | |
) | |
}, | |
test("should greet User if using param") { | |
for | |
response <- greetApp.runZIO( | |
Request.get(URL(!! / "greet").withQueryParams("?name=User")) | |
) | |
body <- response.body.asString | |
yield assertTrue( | |
response.status == Status.Ok, | |
body == "Hello User!" | |
) | |
} | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment