Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate HttpApp and remove internal usage. #2791

Merged
merged 3 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ import zio._
import zio.http._

object GreetingServer extends ZIOAppDefault {
val app =
val routes =
Routes(
Method.GET / "greet" -> handler { (req: Request) =>
val name = req.queryParamToOrElse("name", "World")
Response.text(s"Hello $name!")
}
).toHttpApp
)

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

Expand Down
6 changes: 3 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ import zio._
import zio.http._

object GreetingServer extends ZIOAppDefault {
val app =
val routes =
Routes(
Method.GET / "greet" -> handler { (req: Request) =>
val name = req.queryParamToOrElse("name", "World")
Response.text(s"Hello $name!")
}
).toHttpApp
)

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

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,15 +20,15 @@ import zio._
import zio.http._

object HelloExample extends ZIOAppDefault {
val app: HttpApp[Any] =
val app: Routes[Any, Response] =
Routes(
Method.GET / "hello" ->
handler { req: Request =>
for {
name <- req.body.asString
} yield Response(body = Body.fromString(s"Hello $name!"))
}.sandbox,
).toHttpApp
)

override val run = Server.serve(app).provide(Server.default)
}
Expand Down
10 changes: 5 additions & 5 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 = Routes(
val routes = Routes(
Method.GET / "cookie" -> handler {
Response.ok.addCookie(
Cookie.Response(name = "user_id", content = "user123", maxAge = Some(5.days))
)
},
).toHttpApp
)

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

Expand Down Expand Up @@ -154,7 +154,7 @@ val app =
Method.GET / "cookie" -> handler {
Response.ok.addCookie(cookie.sign("secret"))
}
).toHttpApp
)
```

- Using `signCookies` middleware:
Expand All @@ -167,7 +167,7 @@ import Middleware.signCookies
val app = Routes(
Method.GET / "cookie" -> handler(Response.ok.addCookie(cookie)),
Method.GET / "secure-cookie" -> handler(Response.ok.addCookie(cookie.copy(isSecure = true)))
).toHttpApp
)

// Run it like any simple app
def run(args: List[String]): ZIO[Any, Throwable, Nothing] =
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
24 changes: 12 additions & 12 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(Routes(saveUserRoute, homeRoute).toHttpApp)
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 = Routes(saveUserRoute, getUsersRoute, homeRoute).toHttpApp
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 = Routes(
val routes = Routes(
Method.GET / "set-flash" -> handler {
val setBoth: Flash.Setter[(String, String)] =
Flash.setNotice("The form was submitted successfully!") ++
Expand All @@ -536,9 +536,9 @@ object SetGetBothFlashExample extends ZIOAppDefault {
req.flash(getBoth).getOrElse(ui.renderNoFlash),
)
},
).sandbox.toHttpApp
).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 = Routes(
val routes = Routes(
Method.GET / "set-flash" -> handler {
Response
.seeOther(URL.root / "get-flash")
Expand All @@ -568,9 +568,9 @@ object CookieBasedFlashExample extends ZIOAppDefault {
req.flash(Flash.getNotice[String]).getOrElse("no-flash"),
)
},
).sandbox.toHttpApp
).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 = Routes(
val routes = Routes(
Method.GET / "set-flash" -> handler {
for {
flashBackend <- ZIO.service[Flash.Backend]
Expand All @@ -625,9 +625,9 @@ object FlashBackendExample extends ZIOAppDefault {
notice <- flashBackend.flash(req, Flash.getNotice[String])
} yield Response.text(notice)
},
).sandbox.toHttpApp
).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
8 changes: 4 additions & 4 deletions docs/reference/handler.md
Original file line number Diff line number Diff line change
Expand Up @@ -612,9 +612,9 @@ In this example, the type of the handler before applying the `sandbox` operator

Without the `sandbox` operator, the compiler would complain about the unhandled `Throwable` error.

### Converting a `Handler` to an `HttpApp`
### Converting a `Handler` to an `Routes`

The `Handler#toHttpApp` operator, converts a handler to an `HttpApp` to be served by the `Server`. The following example, shows an HTTP application that serves a simple "Hello, World!" response for all types of incoming requests:
The `Handler#toRoutes` operator, converts a handler to an `Routes` to be served by the `Server`. The following example, shows an HTTP application that serves a simple "Hello, World!" response for all types of incoming requests:

```scala mdoc:compile-only
import zio._
Expand All @@ -623,7 +623,7 @@ import zio.http._
object HelloWorldServer extends ZIOAppDefault {
def run =
Server
.serve(Handler.fromResponse(Response.text("Hello, world!")).toHttpApp)
.serve(Handler.fromResponse(Response.text("Hello, world!")).toRoutes)
.provide(Server.default)
}
```
Expand Down Expand Up @@ -714,7 +714,7 @@ The are similar to the `ZIO` ones, but they are specialized for the `Handler` ty
The first type parameter of the `Handler` is the environment type. This means that a `Handler` can require an environment to run, like a `ZIO` effect. When we create a `Handler`, we can get access to the environment using `ZIO.service*` methods, and finally, we can provide the environment using `Handler#provide*` methods.

:::note
Please note that in most cases, we are not required to provide the environment of the handler in the middle of the routes definition. It is usually done at the end when we are creating the `HttpApp` using the `Server#serve` method.
Please note that in most cases, we are not required to provide the environment of the handler in the middle of the routes definition. It is usually done at the end when we are creating the `Routes` using the `Server#serve` method.
:::

:::note
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/handler_aspect.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ val statsMiddleware: Middleware[Ref[Map[String, Long]]] =
}
```

After attaching these two handler aspects to our `HttpApp`, we have to provide the initial state for the `Ref[Map[String, Long]]` to the whole application's environment:
After attaching these two handler aspects to our `Routes`, we have to provide the initial state for the `Ref[Map[String, Long]]` to the whole application's environment:

```scala
Server.serve(app @@ counterMiddleware @@ statsMiddleware)
Server.serve(routes @@ counterMiddleware @@ statsMiddleware)
.provide(
Server.default,
ZLayer.fromZIO(Ref.make(Map.empty[String, Long]))
Expand Down
Loading
Loading