By Alvin Alexander. Last updated: November 26, 2024
I try not to do this too often, but here’s a currently-incomplete list of ways to define ZIO HTTP routes. I start with some of the simplest examples, and then make them more complicated as I go along:
//> using scala "3"
//> using dep "dev.zio::zio::2.1.13"
//> using dep "dev.zio::zio-http::3.0.1"
import zio.*
import zio.http.*
/**
* See more examples here:
* - https://zio.dev/zio-http/reference/handler
*/
object RoutingExamples extends ZIOAppDefault:
// basic route definitions
val routes1 = Routes(
Method.GET / "hello" -> Handler.text("Hello World!"),
Method.GET / "html1" -> Handler.html("<p>hi 1</p>"),
Method.GET / "html2" -> handler(Response.html("<p>hi 2</p>")),
Method.GET / "json" -> handler(Response.json("""{"message": "Hello"}""")),
// from https://zio.dev/zio-http/reference/handler:
Method.GET / "uuid" ->
handler(Random.nextUUID.map(u => Response.text(u.toString)))
)
// routes with different HTTP methods
val routes2 = Routes(
Method.GET / "api" -> Handler.text("GET request"),
Method.POST / "api" -> Handler.text("POST request"),
Method.PUT / "api" -> Handler.text("PUT request"),
Method.DELETE / "api" -> Handler.text("DELETE request"),
Method.PATCH / "api" -> Handler.text("PATCH request")
)
// routes with path parameters
val routes3 = Routes(
Method.GET / "users" / string("id") -> handler { (id: String, _: Request) =>
Response.text(s"User ID: $id")
},
Method.GET / "users" / string("userId") / "posts" / string("postId") ->
handler { (userId: String, postId: String, _: Request) =>
Response.text(s"User $userId, Post $postId")
}
)
// routes with query parameters
val routes4 = Routes(
Method.GET / "search" -> handler { (req: Request) =>
val query = req.url.queryParams.getAll("q").headOption
Response.text(s"Search query: ${query.getOrElse("none")}")
},
Method.GET / "filter" -> handler { (req: Request) =>
val sort = req.url.queryParams.getAll("sort").headOption.getOrElse("asc")
val limit = req.url.queryParams.getAll("limit").headOption.map(_.toInt).getOrElse(10)
Response.text(s"Sort: $sort, Limit: $limit")
}
)
// routes with request body handling
val routes5 = Routes(
// from https://zio.dev/zio-http/reference/routing/routes
Method.POST / "echo1" ->
handler { (req: Request) =>
req.body.asString.map(Response.text(_))
}.sandbox
,
// echoes the request body
// from https://zio.dev/zio-http/reference/handler
Method.POST / "echo2" ->
handler { (req: Request) =>
req.body.asString(Charsets.Utf8).map(Response.text(_)).orDie
}
,
Method.POST / "json-body" -> handler { (req: Request) =>
req.body.asString.orDie.map { body =>
Response.json(s"""{"received": $body}""")
}
},
Method.POST / "form" -> handler { (req: Request) =>
(for
form <- req.body.asURLEncodedForm
name = form.get("name").getOrElse("anonymous")
yield
Response.text(s"Hello, $name!")).orDie
}
)
// routes with different response types
val routes6 = Routes(
Method.GET / "status" -> Handler.status(Status.Created),
Method.GET / "with-headers" -> handler(
Response.json("""{"status": "ok"}""")
.addHeader(Header.Custom("X-Custom-Header", "value")))
// Method.GET / "binary" ->
// Handler.fromStreamChunked(Chunk.fromArray("Hello".getBytes()))
)
// combining multiple route groups
val allRoutes = routes1 ++ routes2 ++ routes3 ++ routes4 ++ routes5 ++ routes6
// running the server
override def run =
Server.serve(allRoutes)
.provide(Server.default)
As I mentioned, this is a work-in-progress, and I’ll be updating this page over the next few days as I verify all the different possible ZIO HTTP examples.