-
Notifications
You must be signed in to change notification settings - Fork 422
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
zio-http: Use Http.collectHandler #2718
Conversation
Wait, now that I think of it I guess it's how zio-http is handling unmatched routes in I'm not sure this is something we can actually control from the interpreter's side without reintroducing the previous issues (since it would require us to execute everything in order to know if we have a matching route or not). We might need another approach to support it. I'll see if I can figure something out. |
I tried another approach still using @adamw what do you think should be our approach here? Even if the current implementation passes more tests, how it (doesn't) work with middlewares feel pretty problematic to me. Should we disable some of these tests for zio-http? |
Ok, I actually managed to work around by defaulting to the previous implementation in cases of unmatched routes. 🎉 I also added some tests for middleware to verify that they run before the handler. |
Scala 3 seems to dislike the zio-http middleware so I removed those tests. |
Thanks for your work on this! I haven't looked at the new zio-http API, so I'm not familiar with it at all, and I guess I wouldn't be of much help. It is a bit unfortunate that you have to define a The problem with the Also, why do we need both Would you be willing to open an issue in zio-http to suggest some improvements to the routing integration, which we can then leverage? |
Yes, and this is basically a result of zio-http 0.0.4 completely redesigning their model. The idea is to separate the routing and handling of a request into two different, but related data types. My understanding is that the reason for doing so is to be able to be more precise around what middlewares are applicable to what, and that some are only applicable to routing (because they inherently change how the routing works, such as allowing or disallowing a route). You can find more information about it here: zio/zio-http#1916 Not saying I necessarily agree with all the changes, but I think it was needed in order to have sane composition of zio-apps with middlewares.
That would also have made this update considerably easier, but I think it's unlikely to change since they spent most development time between 0.0.3 and 0.0.4 to get rid of that exact behaviour. But of course we can open and raise it :)
Yeah that's an unfortunate consequence of both libraries basically wanting to control routing in this case, I think. I guess another option would be to see if we can find a cheaper way to evaluate if an endpoint should match a request or not on the tapir side?
Yes, the code is very similar but with subtle differences. What we're defining top-level is a routing handler function. If the At first I thought I agree that the implementation isn't ideal, but I'm not sure that we can do better without changes on either side. :/ |
But on the positive side at least with this change it's possible to use routing middleware such as auth with tapir endpoints. 🙂 |
So I took a bit of a deeper dive, and I think I now roughly understand the problem. It seems we are currently not able to efficiently integrate with zio-http, which is unfortunate, but I'll create an issue there and link it so maybe we can improve the situation. Unfortunately tapir can't change the way it performs routing/handling, this is fixed since 1.0. The problem is that deciding if an endpoint matches a request is combined with extracting values from the request - this is a single step. So you've got sth like a I've also removed the Finally, I've fixed (by explicitly adding type params :) ) the tests and enabled them for Scala 3. I agree that while the solution is not perfect, it's better to have an inefficient one than a broken one :) Thanks for your work on this! |
Thanks so much for spending time on this @adamw 🙏
Yeah I think this makes the most sense as well, otherwise we'll essentially be doing error handling twice. Should also make the code much clearer, which is a nice benefit.
Nice! I think I need to up my Scala 3-chops 😂 I saw your issue in zio-http, will be interesting to hear what the zio-http maintainers think! |
This is an attempt to fix #2708. Sorry about getting it wrong the first time, I'm still not completely familiar with the Middleware, Routing and Handler changes in zio-http 0.0.4.
If I understand zio/zio-http#1975 (comment) correctly, the issue with the current interpreter is that we're effectfully creating a handler here, which in turn will result in our interpreter accepting all routes (and more or less doing its internal routing later), which makes the middlewares run incorrectly from the point of view of a user.
This instead tries to adapt the pattern that the play interpreter uses and constructs a
PartialFunction[Request, Handler[R, Throwable, Request, Response]
which we then pass toHttp.collectHandler
, which if I understand it correctly, means we're doing the right thing.I almost have it working, but a couple of tests relating to rejection are failing:
I think this is because we do as the Play interpreter does and setup a custom
DecodeFailureHandler
to use from the partial function, but I'm not sure. And I'm not very familiar with Tapir so could probably use a pointer or two to fix them :)