Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dacr/84f026b451b902be080f31f699e0ac96 to your computer and use it in GitHub Desktop.
Save dacr/84f026b451b902be080f31f699e0ac96 to your computer and use it in GitHub Desktop.
Simple server side event (SSE) using http4s library and zio dependency injection / published by https://github.com/dacr/code-examples-manager #c52505e2-38d1-49ee-8bbc-d8ee46c69c1d/f2a9bdcd84561be43525370801f7e2720fb9494c
// summary : Simple server side event (SSE) using http4s library and zio dependency injection
// keywords : scala, http4s, cats, http-server, tapir, sse, zio, @testable, @exclusive
// publish : gist
// authors : David Crosson
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2)
// id : c52505e2-38d1-49ee-8bbc-d8ee46c69c1d
// created-on : 2024-06-14T13:47:45+02:00
// managed-by : https://github.com/dacr/code-examples-manager
// run-with : scala-cli $file
// test-with : curl http://127.0.0.1:8080/hi
// ---------------------
//> using scala "3.4.2"
//> using dep "com.softwaremill.sttp.tapir::tapir-zio:1.10.9"
//> using dep "com.softwaremill.sttp.tapir::tapir-http4s-server-zio:1.10.9"
//> using dep "com.softwaremill.sttp.tapir::tapir-json-zio:1.10.9"
//> using dep "com.softwaremill.sttp.tapir::tapir-swagger-ui-bundle:1.10.9"
//> using dep "com.softwaremill.sttp.tapir::tapir-openapi-docs:1.10.9"
//> using dep "org.http4s::http4s-blaze-server:0.23.16"
//> using dep "org.slf4j:slf4j-simple:2.0.13"
//> using options -Ykind-projector:underscores // MANDATORY for scala3 kind projector, cats need
// ---------------------
import cats.syntax.all.*
import org.http4s.{ServerSentEvent as _, *}
import org.http4s.blaze.server.BlazeServerBuilder
import org.http4s.server.Router
import org.http4s.implicits.*
import sttp.tapir.PublicEndpoint
import sttp.tapir.generic.auto.*
import sttp.tapir.swagger.bundle.SwaggerInterpreter
import sttp.tapir.server.http4s.ztapir.{ZHttp4sServerInterpreter, serverSentEventsBody}
import sttp.apispec.openapi.Info
import sttp.model.sse.ServerSentEvent
import sttp.tapir.ztapir.*
import zio.interop.catz.*
import zio.{Console, Task, UIO, ZIO, RIO, URIO, ZIOAppDefault, ZLayer}
import zio.durationInt
import zio.stream.*
trait GreetingsService {
def standardGreetings: UIO[List[String]]
}
case class GreetingsServiceLive() extends GreetingsService {
override def standardGreetings: UIO[List[String]] = ZIO.succeed {
List("Hi", "Hello", "Good morning", "How are you")
}
}
object GreetingsService {
def standardGreetings: URIO[GreetingsService, List[String]] = ZIO.serviceWithZIO[GreetingsService](_.standardGreetings)
val live = ZLayer.succeed(GreetingsServiceLive())
}
object Hello extends ZIOAppDefault {
def hiLogic(givenName: Option[String]): URIO[GreetingsService, Stream[Throwable, ServerSentEvent]] = for {
greetings <- GreetingsService.standardGreetings
stream = ZStream
.from(greetings)
.map(greeting => givenName.map(name => s"$greeting $name").getOrElse(greeting))
.forever
.map(greeting => ServerSentEvent(data = Some(greeting)))
.take(10)
} yield stream
val hiEndPoint =
endpoint
.description("Returns many greetings")
.get
.in("hi")
.in(query[Option[String]]("name").description("someone name"))
.out(serverSentEventsBody)
val hiEndPointWired = hiEndPoint.zServerLogic[GreetingsService](hiLogic)
val docEndPointWired =
SwaggerInterpreter()
.fromServerEndpoints(
List(hiEndPointWired),
Info(title = "Greeting API", version = "1.0", description = Some("Everything required to be polite"))
)
val routes: HttpRoutes[RIO[GreetingsService, _]] =
ZHttp4sServerInterpreter()
.from(hiEndPointWired :: docEndPointWired)
.toRoutes
def run = {
ZIO.executor
.flatMap(executor =>
BlazeServerBuilder[RIO[GreetingsService, _]]
.withExecutionContext(executor.asExecutionContext)
.bindLocal(8080)
.withHttpApp(Router("/" -> routes).orNotFound)
.serve
.compile
.drain
)
.timeout(60.seconds)
.provide(GreetingsService.live)
}
}
Hello.main(Array.empty)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment