Skip to content

Commit

Permalink
Remove HttpApp from internal API and examples
Browse files Browse the repository at this point in the history
  • Loading branch information
987Nabil committed Apr 24, 2024
1 parent 8a74e33 commit da912a0
Show file tree
Hide file tree
Showing 129 changed files with 796 additions and 1,054 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import zio.http._

object GreetingServer extends ZIOAppDefault {
val routes =
HttpApp(
Routes(
Method.GET / "greet" -> handler { (req: Request) =>
val name = req.queryParamToOrElse("name", "World")
Response.text(s"Hello $name!")
Expand Down
86 changes: 36 additions & 50 deletions docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ ZIO HTTP has powerful functional domains that help in creating, modifying, and c

The core concepts of ZIO HTTP are:

- `HttpApp` - A collection of `Routes`s that are ready to be served. All errors are handled through conversion into HTTP responses.
- `Routes` - A collection of `Route`s.
- `Route` - A single route that can be matched against an http `Request` and produce a `Response`. It comprises a `RoutePattern` and a `Handler`:
1. `RoutePattern` - A pattern that can be matched against an http request. It is a combination of `Method` and `PathCodec` which can be used to match the method and path of the request.
- `Routes` - A collection of `Route`s. If the error type of the routes is `Response`, then they can be served.
- `Route` - A single route that can be matched against a http `Request` and produce a `Response`. It comprises a `RoutePattern` and a `Handler`:
1. `RoutePattern` - A pattern that can be matched against a http request. It is a combination of `Method` and `PathCodec` which can be used to match the method and path of the request.
2. `Handler` - A function that can convert a `Request` into a `Response`.

Let's see each of these concepts inside a simple example:
Expand All @@ -32,11 +31,11 @@ object ExampleServer extends ZIOAppDefault {
val greetRoute: Route[Any, Nothing] =
// The whole Method.GET / "greet" is a RoutePattern
Method.GET / "greet" ->
// The handler is a function that takes a Request and returns a Response
handler { (req: Request) =>
val name = req.queryParamToOrElse("name", "World")
Response.text(s"Hello $name!")
}
// The handler is a function that takes a Request and returns a Response
handler { (req: Request) =>
val name = req.queryParamToOrElse("name", "World")
Response.text(s"Hello $name!")
}

// A route that matches POST requests to /echo
// It doesn't require any service from the ZIO environment
Expand All @@ -46,27 +45,25 @@ object ExampleServer extends ZIOAppDefault {
req.body.asString.map(Response.text(_))
}

// The HttpApp that doesn't require any service from the ZIO environment,
// The Routes that don't require any service from the ZIO environment,
// so the first type parameter is Any.
// All the errors are handled
val app: HttpApp[Any] =
// All the errors are handled by turning them into a Response.
val routes: Routes[Any, Response] =
// List of all the routes
Routes(greetRoute, echoRoute)
// Handle all unhandled errors
.handleError(e => Response.internalServerError(e.getMessage))
// Convert the routes to an HttpApp
.toHttpApp

// Serving the app using the default server layer on port 8080
def run = Server.serve(app).provide(Server.default)
// Handle all unhandled errors
.handleError(e => Response.internalServerError(e.getMessage))

// Serving the routes using the default server layer on port 8080
def run = Server.serve(routes).provide(Server.default)
}
```

### 1. HttpApp
### 1.Routes

The `HttpApp` provides input-dependent routing to different `Handler` values.
The `Routes` provides input-dependent routing to different `Handler` values.

The `Handler`, `Route` and `Routes` can always be transformed to a `HttpApp` value using the `.toHttpApp` method, in which case the HTTP application will handle incomming routes. Before converting to `HttpApp`, we should handle all unhandled errors, e.g.:
The `Handler` and `Route` can be transformed to `Routes` by the `.toRoutes` method. To serve the routes, all errors should be handled by converting them into a `Response` using for example the `.handleError` method.

```scala mdoc:invisible
import zio.http._
Expand All @@ -78,23 +75,12 @@ val echoRoute: Route[Any, Throwable] = Route.notFound
```scala mdoc:silent
import zio.http._

val app: HttpApp[Any] =
val app: Routes[Any, Response] =
Routes(greetRoute, echoRoute)
.handleError(e => Response.internalServerError(e.getMessage))
.toHttpApp
```

### 2. Routes

For handling routes, ZIO HTTP has a [`Routes`](reference/routes.md) value, which allows us to aggregate a collection of individual routes. Behind the scenes, ZIO HTTP builds an efficient prefix-tree whenever needed to optimize dispatch.

The `Routes` is a collection of `Route` values. It can be created using its default constructor:

```scala mdoc:silent
val routes = Routes(greetRoute, echoRoute)
```

### 3. Route
### 2. Route

Each `Route` is a combination of a [`RoutePattern`](reference/route_pattern.md) and a [`Handler`](reference/handler.md). The `RoutePattern` is a combination of a `Method` and a [`PathCodec`](reference/path_codec.md) that can be used to match the method and path of the request. The `Handler` is a function that can convert a `Request` into a `Response`.

Expand All @@ -113,12 +99,12 @@ val routes = Routes(

To learn more about routes, see the [Routes](reference/routes.md) page.

### 4. Handler
### 3. Handler

The `Handler` describes the transformation from an incoming `Request` to an outgoing `Response`:

```scala mdoc:compile-only
val helloHanlder =
val helloHandler =
handler { (_: Request) =>
Response.text("Hello World!")
}
Expand Down Expand Up @@ -165,18 +151,18 @@ import zio._
import zio.http._

object CounterExample extends ZIOAppDefault {
val app: HttpApp[Ref[Int]] =
val routes: Routes[Ref[Int], Response] =
Routes(
Method.GET / "count" / int("n") ->
handler { (n: Int, _: Request) =>
for {
ref <- ZIO.service[Ref[Int]]
res <- ref.updateAndGet(_ + n)
} yield Response.text(s"Counter: $res")
},
).toHttpApp

def run = Server.serve(app).provide(Server.default, ZLayer.fromZIO(Ref.make(0)))
handler { (n: Int, _: Request) =>
for {
ref <- ZIO.service[Ref[Int]]
res <- ref.updateAndGet(_ + n)
} yield Response.text(s"Counter: $res")
},
)

def run = Server.serve(routes).provide(Server.default, ZLayer.fromZIO(Ref.make(0)))
}
```

Expand Down Expand Up @@ -227,10 +213,10 @@ import zio.http._
import zio._

object HelloWorld extends ZIOAppDefault {
val app = Handler.ok.toHttpApp
val routes = Handler.ok.toRoutes

override def run =
Server.serve(app).provide(Server.defaultWithPort(8090))
Server.serve(routes).provide(Server.defaultWithPort(8090))
}
```

Expand All @@ -257,4 +243,4 @@ object ClientExample extends ZIOAppDefault {
}
```

In the above example, we obtained the `Client` service from the environment and sent a `GET` request to the server. Finally, to run the client app, we provided the default `Client` and `Scope` services to the app. For more information about the client, see the [Client](reference/client.md) page.
In the above example, we obtained the `Client` service from the environment and sent a `GET` request to the server. Finally, to run the client app, we provided the default `Client` and `Scope` services to the app. For more information about the client, see the [Client](reference/client.md) page.
4 changes: 2 additions & 2 deletions docs/reference/body.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import zio._
import zio.http._

object HelloExample extends ZIOAppDefault {
val app: HttpApp[Any, Response] =
HttpApp(
val app: Routes[Any, Response] =
Routes(
Method.GET / "hello" ->
handler { req: Request =>
for {
Expand Down
12 changes: 6 additions & 6 deletions docs/reference/cookies.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ Let's write a simple example to see how it works:
import zio.http._

object ResponseCookieExample extends ZIOAppDefault {
val httpApp = HttpApp(
val routes = Routes(
Method.GET / "cookie" -> handler {
Response.ok.addCookie(
Cookie.Response(name = "user_id", content = "user123", maxAge = Some(5.days))
)
},
)

def run = Server.serve(httpApp).provide(Server.default)
def run = Server.serve(routes).provide(Server.default)
}
```

Expand Down Expand Up @@ -150,7 +150,7 @@ The cookies can be signed with a signature:
```scala mdoc:silent:nest
val cookie = Cookie.Response("key", "hello", maxAge = Some(5.days))
val app =
HttpApp(
Routes(
Method.GET / "cookie" -> handler {
Response.ok.addCookie(cookie.sign("secret"))
}
Expand All @@ -164,7 +164,7 @@ To sign all the cookies in your routes, we can use `signCookies` middleware:
```scala mdoc:silent:nest
import Middleware.signCookies

val app = HttpApp(
val app = Routes(
Method.GET / "cookie" -> handler(Response.ok.addCookie(cookie)),
Method.GET / "secure-cookie" -> handler(Response.ok.addCookie(cookie.copy(isSecure = true)))
)
Expand Down Expand Up @@ -205,7 +205,7 @@ From HTTP requests, a single cookie can be retrieved with `Request#cookie`:

```scala mdoc:compile-only
private val app4 =
HttpApp(
Routes(
Method.GET / "cookie" -> handler { (req: Request) =>
val cookieContent = req.cookie("sessionId").map(_.content)
Response.text(s"cookie content: $cookieContent")
Expand All @@ -219,7 +219,7 @@ In HTTP requests, cookies are stored in the `Header.cookie` header:

```scala mdoc:compile-only
private val app3 =
HttpApp(
Routes(
Method.GET / "cookie" -> handler { (req: Request) =>
Response.text(
req.header(Header.Cookie)
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/endpoint.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ object EndpointWithMultipleOutputTypes extends ZIOAppDefault {
else Left(Quiz("What is the boiling point of water in Celsius?", 2)),
)
})
.toHttpApp).provide(Server.default, Scope.default)
.toRoutes).provide(Server.default, Scope.default)
}
```

Expand Down
18 changes: 9 additions & 9 deletions docs/reference/flash.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ object NotificationWithoutFlash extends ZIOAppDefault {
}


def run = Server.serve(HttpApp(saveUserRoute, homeRoute))
def run = Server.serve(Routes(saveUserRoute, homeRoute))
.provide(Server.default, ZLayer(Ref.make(List.empty[User])))
}
```
Expand Down Expand Up @@ -350,7 +350,7 @@ val getUsersRoute: Route[Ref[List[User]] with Flash.Backend, Nothing] =
} yield Response.html(html ++ usersHTML)
}

val app = HttpApp(saveUserRoute, getUsersRoute, homeRoute)
val app = Routes(saveUserRoute, getUsersRoute, homeRoute)

def run = Server.serve(app).provide(Server.default, Flash.Backend.inMemory, ZLayer(Ref.make(List.empty[User])))
}
Expand Down Expand Up @@ -520,7 +520,7 @@ object ui {
}

object SetGetBothFlashExample extends ZIOAppDefault {
val httpApp = HttpApp(
val routes = Routes(
Method.GET / "set-flash" -> handler {
val setBoth: Flash.Setter[(String, String)] =
Flash.setNotice("The form was submitted successfully!") ++
Expand All @@ -538,7 +538,7 @@ object SetGetBothFlashExample extends ZIOAppDefault {
},
).sandbox

def run = Server.serve(httpApp).provide(Server.default, Flash.Backend.inMemory)
def run = Server.serve(routes).provide(Server.default, Flash.Backend.inMemory)
}
```

Expand All @@ -555,7 +555,7 @@ import zio._
import zio.http._

object CookieBasedFlashExample extends ZIOAppDefault {
val httpApp = HttpApp(
val routes = Routes(
Method.GET / "set-flash" -> handler {
Response
.seeOther(URL.root / "get-flash")
Expand All @@ -570,7 +570,7 @@ object CookieBasedFlashExample extends ZIOAppDefault {
},
).sandbox

def run = Server.serve(httpApp).provide(Server.default)
def run = Server.serve(routes).provide(Server.default)
}
```

Expand Down Expand Up @@ -609,7 +609,7 @@ import zio.http._
import zio.http.template._

object FlashBackendExample extends ZIOAppDefault {
val httpApp = HttpApp(
val routes = Routes(
Method.GET / "set-flash" -> handler {
for {
flashBackend <- ZIO.service[Flash.Backend]
Expand All @@ -627,7 +627,7 @@ object FlashBackendExample extends ZIOAppDefault {
},
).sandbox

def run = Server.serve(httpApp).provide(Server.default, Flash.Backend.inMemory)
def run = Server.serve(routes).provide(Server.default, Flash.Backend.inMemory)
}
```

Expand All @@ -649,7 +649,7 @@ HTTP/1.1 200 OK
content-type: text/plain
content-length: 28

The form was submitted successfully!
The form was submitted successfully!
```

:::note
Expand Down
Loading

0 comments on commit da912a0

Please sign in to comment.