Introduction to ZIO Http
Table of Contents
Http
Creating a "Hello World" app
import zio.http._
val app = Http.text("Hello World!")
An application can be made using any of the available operators on zio.Http
. In the above program for any Http request, the response is always "Hello World!"
.
Routing
import zio.http._
val app = Http.collect[Request] {
case Method.GET -> Root / "fruits" / "a" => Response.text("Apple")
case Method.GET -> Root / "fruits" / "b" => Response.text("Banana")
}
Pattern matching on route is supported by the framework
Composition
import zio.http._
val a = Http.collect[Request] { case Method.GET -> Root / "a" => Response.ok }
val b = Http.collect[Request] { case Method.GET -> Root / "b" => Response.ok }
val app = a <> b
Apps can be composed using the <>
operator. The way it works is, if none of the routes match in a
, or a NotFound
error is thrown from a
, and then the control is passed on to the b
app.
ZIO Integration
val app = Http.collectM[Request] {
case Method.GET -> Root / "hello" => ZIO.succeed(Response.text("Hello World"))
}
Http.collectM
allow routes to return a ZIO effect value.
Accessing the Request
import zio.http._
val app = Http.collect[Request] {
case req @ Method.GET -> Root / "fruits" / "a" =>
Response.text("URL:" + req.url.path.asString + " Headers: " + r.headers)
case req @ Method.POST -> Root / "fruits" / "a" =>
Response.text(req.bodyAsString.getOrElse("No body!"))
}
Testing
Tests suites could be implemented using zio-test
library, as following:
import zio.test._
import zio.http._
import zio.test.Assertion.equalTo
object Spec extends DefaultRunnableSpec {
val app = Http.collect[Request] { case Method.GET -> !! / "text" =>
Response.text("Hello World!")
}
def spec = suite("http")(
test("should be ok") {
val req = ???
val expectedRes = app(req).map(_.status)
assertZIO(expectedRes)(equalTo(Status.Ok))
},
)
}
Socket
Creating a socket app
import zio.socket._
private val socket = Socket.collect[WebSocketFrame] {
case WebSocketFrame.Text("FOO") => ZStream.succeed(WebSocketFrame.text("BAR"))
}
private val app = Http.collect[Request] {
case Method.GET -> Root / "greet" / name => Response.text(s"Greetings {$name}!")
case Method.GET -> Root / "ws" => Response.socket(socket)
}
Server
Starting an Http App
import zio.http._
import zio.http.Server
import zio._
object HelloWorld extends App {
val app = Http.ok
override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] =
Server.start(8090, app).exitCode
}
A simple Http app that responds with empty content and a 200
status code is deployed on port 8090
using Server.start
.