now using ZIO-http, currently trying to familiarize with this new library

production
Override-6 2 years ago
parent caef1e2364
commit 04924ee757

@ -1,5 +1,6 @@
group "org.tbasket.api"
dependencies {
implementation 'com.typesafe.akka:akka-http_2.13:10.5.0-M1'
api 'dev.zio:zio-http_2.13:0.0.3'
api "dev.zio:zio_2.13:2.0.4"
}

@ -0,0 +1,3 @@
package org.tbasket.api
class APIException(msg: String, cause: Throwable = null) extends Exception

@ -1,38 +1,39 @@
package org.tbasket.api
import akka.actor.typed.ActorSystem
import akka.actor.typed.javadsl.Behaviors
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpResponse}
import akka.http.scaladsl.server.Directives._
import scala.concurrent.ExecutionContextExecutor
class Endpoint(url: String, port: Int) {
implicit val system: ActorSystem[_] = ActorSystem(Behaviors.empty, "main")
implicit val ec : ExecutionContextExecutor = system.executionContext
private var count = 0
def countEntity = HttpEntity(ContentTypes.`application/json`, s"value: $count")
private val server = Http().newServerAt(url, port)
server.bind(concat(
path("counter") {
get {
println("got get request")
complete(countEntity)
}
},
path("counter") {
post {
println("got request")
count += 1
complete(HttpResponse(entity = countEntity))
}
}
))
import org.tbasket.api.compute.APIRequestHandler
import zio._
import zio.http.ServerConfig.LeakDetectionLevel
import zio.http._
import scala.collection.mutable
class Endpoint(hostname: String, port: Int, rootPath: Option[String]) extends ZIOAppDefault {
private val Root: Path = rootPath.map(Path.decode).getOrElse(Path.root)
private val handlers = mutable.HashMap.empty[String, APIRequestHandler]
def bind(path: String)(handler: APIRequestHandler): Unit = {
handlers.put(path, handler)
}
private val app = Http.collectZIO[Request] {
case r@_ -> Root / path if handlers.contains(path) =>
for {
handler <- handlers.get(path)
_ <- handler.handle
} yield ()
case _ -> path =>
ZIO.fail(new APIException(s"Unable to find a handler for page '$path'"))
}
val run = {
val config = ServerConfig.default
.port(port)
.leakDetection(LeakDetectionLevel.PARANOID)
val configLayer = ServerConfig.live(config)
(Server.install(app).flatMap { port =>
Console.printLine(s"Listening API entries on $hostname:$port$rootPath")
} *> ZIO.never).provide(configLayer, Server.live)
}
}

@ -0,0 +1,11 @@
package org.tbasket.api.compute
import org.tbasket.api.APIException
import zio.ZIO
import zio.http.{Request, Response}
trait APIRequestHandler {
def handle: ZIO[Request, APIException, Response]
}

@ -1,7 +0,0 @@
package org.tbasket.api.event
trait RequestHandler {
def handle()
}

@ -1,5 +1,6 @@
plugins {
id 'java'
id 'java-library'
id 'scala'
id 'application'
}
@ -19,7 +20,6 @@ dependencies {
implementation project(':API')
implementation project(':DB')
implementation "io.circe:circe-core_$scalaVersion:0.15.0-M1"
}
test {
@ -32,6 +32,7 @@ run {
allprojects {
apply plugin: 'scala'
apply plugin: 'java-library'
version '1.0-SNAPSHOT'
repositories {
@ -43,8 +44,6 @@ allprojects {
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
implementation "org.scala-lang:scala-library:$scalaVersion.10"
implementation "com.typesafe.akka:akka-actor-typed_$scalaVersion:2.7.0"
implementation "com.typesafe.akka:akka-stream-typed_$scalaVersion:2.7.0"
}

@ -1,6 +1,7 @@
package org.tbasket
import org.tbasket.api.Endpoint
import org.tbasket.compute.IncrementHandler
import java.util.Properties
@ -12,7 +13,7 @@ object EndpointSetup {
def setupEndpoint(): Endpoint = {
println("Initializing API endpoint...")
val endpoint = createEndpoint()
endpoint.bind("counter")(IncrementHandler)
endpoint
}
@ -20,13 +21,13 @@ object EndpointSetup {
val properties = new Properties()
val in = getClass.getClassLoader.getResourceAsStream("server.properties")
properties.load(in)
val (url, port) = properties
val (hostname, port, endpointPath) = properties
.getProperty(EndpointUrl, EndpointUrlDefault) match {
case s"$ip:$port/$endpointPath" => (ip + "/" + endpointPath, port.toInt)
case s"$ip:$port" => (ip, port.toInt)
case s"$ip:$port/$endpointPath" => (ip, port.toInt, Some(endpointPath))
case s"$ip:$port" => (ip, port.toInt, None)
case v => throw new InternalBasketServerException(s"$EndpointUrl property value is wrong: $v must be <ip>:<port>/[endpointPath]")
}
new Endpoint(url, port)
new Endpoint(hostname, port, endpointPath)
}
}

@ -1,15 +1,26 @@
package org.tbasket
import zio._
import scala.io.StdIn
import scala.util.control.NonFatal
object Main {
def main(args: Array[String]): Unit = {
val endpoint = EndpointSetup.setupEndpoint()
val runtime = Runtime.default
Unsafe.unsafe { implicit u =>
runtime.unsafe.run(endpoint.run).catchSome {
case NonFatal(e) =>
e.printStackTrace()
throw e
}
}
println("enter to exit")
StdIn.readLine()
}
}

@ -0,0 +1,20 @@
package org.tbasket.compute
import org.tbasket.api.APIException
import org.tbasket.api.compute.APIRequestHandler
import zio.ZIO
import zio.http.model.Method._
import zio.http.{Request, Response}
object IncrementHandler extends APIRequestHandler {
private var i = 0
override def handle: ZIO[Request, APIException, Response] = {
case GET -> _ => Response.json(s"value: $i")
case POST -> _ =>
i += 1
Response.ok
}
}