-
Notifications
You must be signed in to change notification settings - Fork 415
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
Provide context to multiple routes (#2488) #2553
Conversation
86c387b
to
5dfa064
Compare
Codecov ReportAttention: Patch coverage is
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## main #2553 +/- ##
==========================================
- Coverage 64.56% 64.41% -0.16%
==========================================
Files 148 148
Lines 8649 8660 +11
Branches 1573 1563 -10
==========================================
- Hits 5584 5578 -6
- Misses 3065 3082 +17 ☔ View full report in Codecov by Sentry. |
Some random thoughts, only by looking at the code, did not play with it:
On the other hand, I this proposal solves one special case when you want one context-providing middleware to provide context to a set of routes - which I think is a quite common case so maybe worth to introduce something "special" like this to help that use case. |
@vigoo The middleware at the beginning is already the case if you define it per route. If you provide something without a context, nothing happens. You define just the routes like it would not be there. To the second point, I agree. That is why this is a POC. What I try to proof is, that you can construct routes without a lot of type annotations and still provide a context. The API design / syntax is something different. But I can't imagine there is no way to find a solution for that. How beautiful it will be, I can't tell. But I think we are a step closer to something usable. |
@jdegoes ping! You wanted to give me some feedback. |
@@ -64,6 +64,13 @@ final case class RoutePattern[A](method: Method, pathCodec: PathCodec[A]) { self | |||
): Route[Env, Err] = | |||
Route.route(Route.Builder(self, HandlerAspect.identity))(handler)(zippable.zippable, trace) | |||
|
|||
def -->[Env, Err, I, Ctx, In](handler: Handler[Env, Err, I, Response])(implicit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are going to use -->
for this, then we should make sure to be consistent across all of ZIO HTTP.
In addition: We should give this a named variant too, rather than just the symbolic operator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you be more specific on being consistent with what? I don't even say we should use it, but it was not possible to simply overload ->
cd791d9
to
456a8cb
Compare
456a8cb
to
957a088
Compare
@jdegoes I took a look again after letting intentionally some time pass. Which was good, since I managed to remove the new I did this by restructuring the code for the I provided a method currently called def build[Env, Err, Ctx](
route: Route.Builder[Env, _, Ctx, _, Err],
routes: Route.Builder[Env, _, Ctx, _, Err]*,
): Routes.Builder[Env, Ctx, Err] =
Routes.Builder[Env, Ctx, Err](route +: routes) And added a builder case class Builder[Env, Ctx, Err](routes: Seq[Route.Builder[Env, _, Ctx, _, Err]]){
def @@(aspect: HandlerAspect[Env, Ctx]): Routes[Env, Err] =
new Routes(Chunk.fromIterable(routes.map(_ @@ aspect)))
} Which leads to the syntax Routes.build(
Method.GET / "a" -> handler((ctx: AuthContext, _: Request) => Response.text(ctx.value)),
Method.GET / "b" / int("id") -> handler((id: Int, ctx: AuthContext, _: Request) =>
Response.text(s"for id: $id: ${ctx.value}"),
),
Method.GET / "c" / string("name") -> handler((name: String, ctx: AuthContext, _: Request) =>
Response.text(s"for name: $name: ${ctx.value}"),
),
) @@ basicAuthContextM Now we have basically two choices: We leave the code structure wise as it is right now Which means constructing routes inside of the two constructors val route = Method.GET / "endpoint" -> handler { (_: Request) =>
ZIO.fail(new Exception("hmm..."))
} This would need an explicit type to resolve to the right version of val route: Route[Any, Exception] = Method.GET / "endpoint" -> handler { (_: Request) =>
ZIO.fail(new Exception("hmm..."))
}
val route: Route.Builder[Any, (Int, AuthContext), AuthContext, (Int, AuthContext, Request), Nothing] = Method.GET / "b" / int("id") ->
handler((id: Int, ctx: AuthContext, _: Request) => Response.text(s"for id: $id: ${ctx.value}"),
) Have two different operators Maybe the first solution could be more attractive, if we would have a way of simplifying the type parameters of Anyhow, I am sure this is a step forward overall. @adamgfraser @vigoo Maybe you have some thoughts on this too. |
This PR is not good to go, but shows that I found a way how to provide a context to multiple routes without any more explicit typing or extremely strange syntax.
RFC and I happily accept suggestions on the syntax.
/claim #2488