Last active
February 3, 2026 20:18
-
-
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/659b14a3ed7b0c4b097c396ec8969d6eb4583e88
This file contains hidden or 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
| // 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 License Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) | |
| // 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