Skip to content

Instantly share code, notes, and snippets.

@dacr
Last active May 25, 2024 08:39
Show Gist options
  • Save dacr/21d57f597a6805c6166df8b39a822a80 to your computer and use it in GitHub Desktop.
Save dacr/21d57f597a6805c6166df8b39a822a80 to your computer and use it in GitHub Desktop.
http server random hello world using a sealed trait data structure / published by https://github.com/dacr/code-examples-manager #e9f0b49b-8116-417e-a68a-fc5dd73121df/aaf97c399599d338798043d5b9212211b29583ff
// summary : http server random hello world using a sealed trait data structure
// keywords : scala, zio, tapir, http, zhttp, @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 : e9f0b49b-8116-417e-a68a-fc5dd73121df
// created-on : 2024-01-24T08:42:05+01:00
// managed-by : https://github.com/dacr/code-examples-manager
// run-with : scala-cli $file
// test-with : curl -L http://127.0.0.1:8080/hello
// ---------------------
//> using scala "3.4.2"
//> using dep "com.softwaremill.sttp.tapir::tapir-zio:1.9.6"
//> using dep "com.softwaremill.sttp.tapir::tapir-json-zio:1.9.6"
//> using dep "com.softwaremill.sttp.tapir::tapir-zio-http-server:1.9.6"
//> using dep "com.softwaremill.sttp.tapir::tapir-swagger-ui-bundle:1.9.6"
// ---------------------
import zio.*
import zio.http.Server
import zio.json.{JsonCodec, jsonDiscriminator}
import sttp.tapir.json.zio.*
import sttp.tapir.ztapir.*
import sttp.tapir.server.ziohttp.ZioHttpInterpreter
import sttp.apispec.openapi.Info
import sttp.tapir.Schema
import sttp.tapir.generic.Configuration
import sttp.tapir.swagger.bundle.SwaggerInterpreter
import sttp.tapir.generic.auto.*
/*
curl -L http://127.0.0.1:8080/docs
*/
@jsonDiscriminator("@kind")
sealed trait Feedback derives JsonCodec
case class Message(text: String) extends Feedback derives JsonCodec
@jsonDiscriminator("@kind")
sealed trait Greetings derives JsonCodec
case class Simple(message: Feedback) extends Greetings derives JsonCodec
case class Polite(tile: Int, message: Feedback) extends Greetings derives JsonCodec
object WebApp extends ZIOAppDefault {
implicit val tapirConfig: Configuration =
Configuration.default
.withDiscriminator("@kind")
// .withSnakeCaseMemberNames
// .withKebabCaseDiscriminatorValues
// ----------------------------------------------------
// see https://github.com/softwaremill/tapir/issues/3476
// see https://stackoverflow.com/questions/77739438/generate-right-schema-and-documentation-with-tapir-and-sealed-traits
given Schema[Message] = Schema.derived[Message].title(classOf[Message].getSimpleName)
given Schema[Simple] = Schema.derived[Simple].title(classOf[Simple].getSimpleName)
given Schema[Polite] = Schema.derived[Polite].title(classOf[Polite].getSimpleName)
// ----------------------------------------------------
val helloEndPoint =
endpoint
.description("say hello")
.get
.in("hello")
.out(jsonBody[Feedback])
val helloRoute = helloEndPoint.zServerLogic[Any](_ => ZIO.succeed(Message("Hello")))
// --------------------------------------------------
val greetingEndPoint =
endpoint
.description("Return random greeting")
.get
.in("greeting")
.out(jsonBody[Greetings])
val greetings = List[Greetings](
Simple(Message("Hi")),
Simple(Message("Hello")),
Polite(30, Message("Nice to meed you"))
)
val greetingRoute = greetingEndPoint.zServerLogic[Any](_ => Random.shuffle(greetings).map(_.head))
// --------------------------------------------------
val docEndpoints =
SwaggerInterpreter()
.fromServerEndpoints(
List(helloRoute, greetingRoute),
Info(title = "Greeting API", version = "1.0", description = Some("Everything required to be polite"))
)
// --------------------------------------------------
val routes = ZioHttpInterpreter().toHttp(List(helloRoute, greetingRoute) ++ docEndpoints)
// --------------------------------------------------
override def run =
Server
.serve(routes)
.provide(Server.default)
}
WebApp.main(Array.empty)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment