Skip to content

Commit 8c8f4d1

Browse files
authored
feat(tonic): add Interceptor trait (#713)
* Expose `Interceptor` trait. * Revert changes to public API surface. * Rename types, add deprecated alias for old names.
1 parent 0e33a02 commit 8c8f4d1

File tree

9 files changed

+75
-26
lines changed

9 files changed

+75
-26
lines changed

examples/src/tower/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
1515

1616
let channel = ServiceBuilder::new()
1717
// Interceptors can be also be applied as middleware
18-
.layer(tonic::service::interceptor_fn(intercept))
18+
.layer(tonic::service::interceptor(intercept))
1919
.layer_fn(AuthSvc::new)
2020
.service(channel);
2121

examples/src/tower/server.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
4747
// Apply our own middleware
4848
.layer(MyMiddlewareLayer::default())
4949
// Interceptors can be also be applied as middleware
50-
.layer(tonic::service::interceptor_fn(intercept))
50+
.layer(tonic::service::interceptor(intercept))
5151
.into_inner();
5252

5353
Server::builder()

tonic-build/src/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub fn generate<T: Service>(
6868

6969
pub fn with_interceptor<F>(inner: T, interceptor: F) -> #service_ident<InterceptedService<T, F>>
7070
where
71-
F: FnMut(tonic::Request<()>) -> Result<tonic::Request<()>, tonic::Status>,
71+
F: tonic::service::Interceptor,
7272
T: tonic::codegen::Service<
7373
http::Request<tonic::body::BoxBody>,
7474
Response = http::Response<<T as tonic::client::GrpcService<tonic::body::BoxBody>>::ResponseBody>

tonic-build/src/server.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ pub fn generate<T: Service>(
104104

105105
pub fn with_interceptor<F>(inner: T, interceptor: F) -> InterceptedService<Self, F>
106106
where
107-
F: FnMut(tonic::Request<()>) -> Result<tonic::Request<()>, tonic::Status>,
107+
F: tonic::service::Interceptor,
108108
{
109109
InterceptedService::new(Self::new(inner), interceptor)
110110
}

tonic/src/extensions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use std::fmt;
22

33
/// A type map of protocol extensions.
44
///
5-
/// `Extensions` can be used by [`interceptor_fn`] and [`Request`] to store extra data derived from
5+
/// `Extensions` can be used by [`Interceptor`] and [`Request`] to store extra data derived from
66
/// the underlying protocol.
77
///
8-
/// [`interceptor_fn`]: crate::service::interceptor_fn
8+
/// [`Interceptor`]: crate::service::Interceptor
99
/// [`Request`]: crate::Request
1010
pub struct Extensions {
1111
inner: http::Extensions,

tonic/src/request.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,13 +300,13 @@ impl<T> Request<T> {
300300
/// Extensions can be set in interceptors:
301301
///
302302
/// ```no_run
303-
/// use tonic::{Request, service::interceptor_fn};
303+
/// use tonic::{Request, service::interceptor};
304304
///
305305
/// struct MyExtension {
306306
/// some_piece_of_data: String,
307307
/// }
308308
///
309-
/// interceptor_fn(|mut request: Request<()>| {
309+
/// interceptor(|mut request: Request<()>| {
310310
/// request.extensions_mut().insert(MyExtension {
311311
/// some_piece_of_data: "foo".to_string(),
312312
/// });

tonic/src/service/interceptor.rs

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! gRPC interceptors which are a kind of middleware.
22
//!
3-
//! See [`interceptor_fn`] for more details.
3+
//! See [`Interceptor`] for more details.
44
55
use crate::{request::SanitizeHeaders, Status};
66
use pin_project::pin_project;
@@ -13,12 +13,15 @@ use std::{
1313
use tower_layer::Layer;
1414
use tower_service::Service;
1515

16-
/// Create a new interceptor from a function.
16+
/// A gRPC incerceptor.
1717
///
1818
/// gRPC interceptors are similar to middleware but have less flexibility. An interceptor allows
1919
/// you to do two main things, one is to add/remove/check items in the `MetadataMap` of each
2020
/// request. Two, cancel a request with a `Status`.
2121
///
22+
/// Any function that satisfies the bound `FnMut(Request<()>) -> Result<Request<()>, Status>` can be
23+
/// used as an `Interceptor`.
24+
///
2225
/// An interceptor can be used on both the server and client side through the `tonic-build` crate's
2326
/// generated structs.
2427
///
@@ -35,24 +38,56 @@ use tower_service::Service;
3538
/// [tower]: https://crates.io/crates/tower
3639
/// [example]: https://github.com/hyperium/tonic/tree/master/examples/src/interceptor
3740
/// [tower-example]: https://github.com/hyperium/tonic/tree/master/examples/src/tower
38-
pub fn interceptor_fn<F>(f: F) -> InterceptorFn<F>
41+
pub trait Interceptor {
42+
/// Intercept a request before it is sent, optionally cancelling it.
43+
fn call(&mut self, request: crate::Request<()>) -> Result<crate::Request<()>, Status>;
44+
}
45+
46+
impl<F> Interceptor for F
3947
where
4048
F: FnMut(crate::Request<()>) -> Result<crate::Request<()>, Status>,
4149
{
42-
InterceptorFn { f }
50+
fn call(&mut self, request: crate::Request<()>) -> Result<crate::Request<()>, Status> {
51+
self(request)
52+
}
53+
}
54+
55+
/// Create a new interceptor layer.
56+
///
57+
/// See [`Interceptor`] for more details.
58+
pub fn interceptor<F>(f: F) -> InterceptorLayer<F>
59+
where
60+
F: Interceptor,
61+
{
62+
InterceptorLayer { f }
4363
}
4464

45-
/// An interceptor created from a function.
65+
#[deprecated(
66+
since = "0.5.1",
67+
note = "Please use the `interceptor` function instead"
68+
)]
69+
/// Create a new interceptor layer.
4670
///
47-
/// See [`interceptor_fn`] for more details.
71+
/// See [`Interceptor`] for more details.
72+
pub fn interceptor_fn<F>(f: F) -> InterceptorLayer<F>
73+
where
74+
F: Interceptor,
75+
{
76+
interceptor(f)
77+
}
78+
79+
/// A gRPC interceptor that can be used as a [`Layer`],
80+
/// created by calling [`interceptor`].
81+
///
82+
/// See [`Interceptor`] for more details.
4883
#[derive(Debug, Clone, Copy)]
49-
pub struct InterceptorFn<F> {
84+
pub struct InterceptorLayer<F> {
5085
f: F,
5186
}
5287

53-
impl<S, F> Layer<S> for InterceptorFn<F>
88+
impl<S, F> Layer<S> for InterceptorLayer<F>
5489
where
55-
F: FnMut(crate::Request<()>) -> Result<crate::Request<()>, Status> + Clone,
90+
F: Interceptor + Clone,
5691
{
5792
type Service = InterceptedService<S, F>;
5893

@@ -61,9 +96,19 @@ where
6196
}
6297
}
6398

99+
#[deprecated(
100+
since = "0.5.1",
101+
note = "Please use the `InterceptorLayer` type instead"
102+
)]
103+
/// A gRPC interceptor that can be used as a [`Layer`],
104+
/// created by calling [`interceptor`].
105+
///
106+
/// See [`Interceptor`] for more details.
107+
pub type InterceptorFn<F> = InterceptorLayer<F>;
108+
64109
/// A service wrapped in an interceptor middleware.
65110
///
66-
/// See [`interceptor_fn`] for more details.
111+
/// See [`Interceptor`] for more details.
67112
#[derive(Clone, Copy)]
68113
pub struct InterceptedService<S, F> {
69114
inner: S,
@@ -75,7 +120,7 @@ impl<S, F> InterceptedService<S, F> {
75120
/// function `F`.
76121
pub fn new(service: S, f: F) -> Self
77122
where
78-
F: FnMut(crate::Request<()>) -> Result<crate::Request<()>, Status>,
123+
F: Interceptor,
79124
{
80125
Self { inner: service, f }
81126
}
@@ -95,7 +140,7 @@ where
95140

96141
impl<S, F, ReqBody, ResBody> Service<http::Request<ReqBody>> for InterceptedService<S, F>
97142
where
98-
F: FnMut(crate::Request<()>) -> Result<crate::Request<()>, Status>,
143+
F: Interceptor,
99144
S: Service<http::Request<ReqBody>, Response = http::Response<ResBody>>,
100145
S::Error: Into<crate::Error>,
101146
{
@@ -113,7 +158,10 @@ where
113158
let req = crate::Request::from_http(req);
114159
let (metadata, extensions, msg) = req.into_parts();
115160

116-
match (self.f)(crate::Request::from_parts(metadata, extensions, ())) {
161+
match self
162+
.f
163+
.call(crate::Request::from_parts(metadata, extensions, ()))
164+
{
117165
Ok(req) => {
118166
let (metadata, extensions, _) = req.into_parts();
119167
let req = crate::Request::from_parts(metadata, extensions, msg);

tonic/src/service/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
pub mod interceptor;
44

55
#[doc(inline)]
6-
pub use self::interceptor::interceptor_fn;
6+
#[allow(deprecated)]
7+
pub use self::interceptor::{interceptor, interceptor_fn, Interceptor};

tonic/src/transport/server/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ impl<L> Server<L> {
395395
/// # use tower_service::Service;
396396
/// use tower::ServiceBuilder;
397397
/// use std::time::Duration;
398-
/// use tonic::{Request, Status, service::interceptor_fn};
398+
/// use tonic::{Request, Status, service::interceptor};
399399
///
400400
/// fn auth_interceptor(request: Request<()>) -> Result<Request<()>, Status> {
401401
/// if valid_credentials(&request) {
@@ -417,8 +417,8 @@ impl<L> Server<L> {
417417
/// let layer = ServiceBuilder::new()
418418
/// .load_shed()
419419
/// .timeout(Duration::from_secs(30))
420-
/// .layer(interceptor_fn(auth_interceptor))
421-
/// .layer(interceptor_fn(some_other_interceptor))
420+
/// .layer(interceptor(auth_interceptor))
421+
/// .layer(interceptor(some_other_interceptor))
422422
/// .into_inner();
423423
///
424424
/// Server::builder().layer(layer);
@@ -428,7 +428,7 @@ impl<L> Server<L> {
428428
/// [`Layer`]: tower::layer::Layer
429429
/// [eco]: https://github.com/tower-rs
430430
/// [`ServiceBuilder`]: tower::ServiceBuilder
431-
/// [interceptors]: crate::service::interceptor_fn
431+
/// [interceptors]: crate::service::Interceptor
432432
pub fn layer<NewLayer>(self, new_layer: NewLayer) -> Server<NewLayer> {
433433
Server {
434434
layer: new_layer,

0 commit comments

Comments
 (0)