-
Notifications
You must be signed in to change notification settings - Fork 1k
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
feat(tonic): make it easier to add tower middleware to servers #651
Conversation
Update: Interceptors can now be added with fn intercept(req: Request<()>) -> Result<Request<()>, Status> {
Ok(req)
}
Server::builder()
.layer(tonic::service::interceptor_fn(intercept))
.add_service(svc)
.serve(addr)
.await?; And since Edit: Might have gone a bit overboard but I actually went ahead and implemented the old intercept API on top of the new tower interceptors. Still a breaking change of course but I don't think there is much reason to keep both APIs around. |
Converting this back to a draft. Wanna see if I can find a solution to
That means you currently cannot use middleware that change the body type which quite a few in tower-http does, namely |
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.
Everything looks good to me, I see you still have a few things to check but approving since I trust you to complete those before merging! I love this PR!
@@ -1,8 +1,9 @@ | |||
use hello_world::greeter_client::GreeterClient; | |||
use hello_world::HelloRequest; | |||
use service::AuthSvc; | |||
use tower::ServiceBuilder; |
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.
should tonic re-export? Or even better could the channel build expose a way to get the servicebuilder?
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.
I considered that as well but opted not to. Since ServiceBuilder
isn't very useful on its own its not clear which other things from tower we would also have to re-export.
I might consider adding some convenience stuff to channel builders but I think I'll do that as a separate PR.
/// | ||
/// [tower]: https://crates.io/crates/tower | ||
/// [example]: https://github.com/hyperium/tonic/tree/master/examples/src/interceptor | ||
// TODO: when tower-http is shipped update the docs to mention its `Trace` middleware which has |
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.
gh issue for this?
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.
yes!
4b249d9
to
f16c09b
Compare
Doesn't this refactor break the In my derived example: error[E0308]: mismatched types
--> src/mymodule.rs:27:8
|
27 | Ok(client)
| ^^^^^^ expected struct `Channel`, found struct `tonic::codegen::InterceptedService`
|
= note: expected struct `MyClient<Channel>`
found struct `MyClient<tonic::codegen::InterceptedService<Channel, fn(tonic::Request<()>) -> Result<tonic::Request<()>, tonic::Status> {intercept}>>` |
@drauschenbach indeed it does. That's why it was released as part of tonic 0.5, the previous version being 0.4.x |
This is an attempt at making tower easier to use with tonic. It only touches the server parts because I think adding tower middleware to a client is already easy.
The main limitations of the current setup I think are:
NamedService
. This is big downside because it means middleware defined in tower cannot be used since tower doesn't know anything about tonic.http::Request
andhttp::Response
to work with tonic. Thats quite surprising since tonic already has its own request and response types.What I have so far solves 1 and 2. I'm not quite sure 3 has a good solution but might be possible to write a middleware that converts things back and forth behind the scenes.
Using tower now
With this patch adding tower middleware to a tonic server looks like:
So
Server
andRouter
becomes generic over a tower layer. The layer starts out asIdentity
but can be changed with theServer::layer
method. The layer will be applied before handing the service off to hyper viaMakeSvc
.Server::layer
will show up in the docs and gives us a place to mention and demo using tower to add middleware. That should hopefully increase awareness a bit.TODO
Things to fix should be decide to move forward with this.
with_interceptor
constructors to use InterceptedServiceBoxBody
as bounds for services inadd_service
andadd_optional_service
as that requiresError = Status
.Fixes #372 #499 #70
Ref #69