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

Document HandlerAspect in middleware.md #2729

Merged
merged 6 commits into from
Apr 5, 2024
Merged
Changes from 2 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
34 changes: 34 additions & 0 deletions docs/dsl/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,37 @@ object Example extends ZIOAppDefault {
- [CORS](https://zio.github.io/zio-http/docs/v1.x/examples/advanced-examples/middleware_cors)
- [CSRF](https://zio.github.io/zio-http/docs/v1.x/examples/advanced-examples/middleware_csrf)

## Handler Aspects

Ordinary Middlewares are intended to bracket a request's execution by intercepting the request, possibly modifying it or short-circuiting its execution
(for example if it fails authentication), and then performing some post-processing on the response.
However, we sometimes want to gather some contextual information about a request and pass it alongside to the request's handler.
This can be achieved with the `HandlerAspect[Env, CtxOut]` type, which extends `Middleware[Env]`.
This middleware produces a value of type `CtxOut` on each request, which the routing DSL will accept just like a path component:

```scala
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please try to use the mdoc as much as possible for snippet codes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, though I don't know how much that adds here, since these snippets won't compile as written.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal is to make the code snippets maintainable by ensuring they can be compiled against the source code. So the "crash" modifier isn't helpful in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't use crash but rather fail (the former is for code that compiles but fails at runtime, the latter for code that won't compile in the first place).

In any case, I had to resort to the hack of a mdoc:invisible block to declare some names.

val sessionMiddleware: HandlerAspect[Env, Session] = createSessionMiddleware()
Routes(
Method.GET / "user" / int("userId") -> sessionMiddleware -> handler { (userId: Int, session: Session, request: Request) =>
UserRepository.getUser(session.organizationId, userId)
}
)
```

In order to implement `createSessionMiddleware` in our example, we will need one or more `Handler`s:
```scala
def createSessionMiddleware[Env](): HandlerAspect[Env, Session] = {
val incomingHandler: Handler[Env, Response, Request, (Request, Session)] =
// session lookup logic here

HandlerAspect.interceptIncomingHandler(incomingHandler)

// or, if post-processing of the response is needed,
val outgoingHandler: Handler[Env, Nothing, Response, Response] =
// post-processing logic here
HandlerAspect.interceptHandler(incomingHandler)(outgoingHandler)
}
```
Note the asymmetry of the type parameters of these two handlers:
In the incoming case, the `Err` parameter is `Response`; if the handler cannot produce a `Session`, then it is responsible for generating an error `Response` which will be returned to the client (possibly with modifications by other middlewares).
The outgoing handler, by contrast, has `Nothing` as its `Err` type, meaning that it **cannot** fail and must always produce a `Response`.
Loading