Last active
May 25, 2024 08:39
-
-
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
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 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