Skip to content

Commit 6dfc20e

Browse files
authored
feat(transport): port router to axum (#830)
1 parent 0f7344a commit 6dfc20e

File tree

8 files changed

+146
-310
lines changed

8 files changed

+146
-310
lines changed

tonic-build/src/server.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ pub fn generate<T: Service>(
124124
B::Error: Into<StdError> + Send + 'static,
125125
{
126126
type Response = http::Response<tonic::body::BoxBody>;
127-
type Error = Never;
127+
type Error = std::convert::Infallible;
128128
type Future = BoxFuture<Self::Response, Self::Error>;
129129

130130
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {

tonic/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ tls-roots = ["tls-roots-common", "rustls-native-certs"]
3232
tls-roots-common = ["tls"]
3333
tls-webpki-roots = ["tls-roots-common", "webpki-roots"]
3434
transport = [
35+
"axum",
3536
"h2",
3637
"hyper",
3738
"tokio",
@@ -77,6 +78,7 @@ tokio = {version = "1.0.1", features = ["net"], optional = true}
7778
tokio-stream = "0.1"
7879
tower = {version = "0.4.7", features = ["balance", "buffer", "discover", "limit", "load", "make", "timeout", "util"], optional = true}
7980
tracing-futures = {version = "0.2", optional = true}
81+
axum = {version = "0.4", default_features = false, optional = true}
8082

8183
# rustls
8284
rustls-pemfile = { version = "0.2.1", optional = true }

tonic/src/body.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ use http_body::Body;
55
/// A type erased HTTP body used for tonic services.
66
pub type BoxBody = http_body::combinators::UnsyncBoxBody<bytes::Bytes, crate::Status>;
77

8+
/// Convert a [`http_body::Body`] into a [`BoxBody`].
9+
pub(crate) fn boxed<B>(body: B) -> BoxBody
10+
where
11+
B: http_body::Body<Data = bytes::Bytes> + Send + 'static,
12+
B::Error: Into<crate::Error>,
13+
{
14+
body.map_err(crate::Status::map_error).boxed_unsync()
15+
}
16+
817
// this also exists in `crate::codegen` but we need it here since `codegen` has
918
// `#[cfg(feature = "codegen")]`.
1019
/// Create an empty `BoxBody`

tonic/src/codegen.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,6 @@ pub mod http {
2424
pub use http::*;
2525
}
2626

27-
#[derive(Debug)]
28-
pub enum Never {}
29-
30-
impl std::fmt::Display for Never {
31-
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32-
match *self {}
33-
}
34-
}
35-
36-
impl std::error::Error for Never {}
37-
3827
pub fn empty_body() -> crate::body::BoxBody {
3928
http_body::Empty::new()
4029
.map_err(|err| match err {})

tonic/src/service/interceptor.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
//!
33
//! See [`Interceptor`] for more details.
44
5-
use crate::{request::SanitizeHeaders, Status};
5+
use crate::{
6+
body::{boxed, BoxBody},
7+
request::SanitizeHeaders,
8+
Status,
9+
};
610
use bytes::Bytes;
711
use pin_project::pin_project;
812
use std::{
@@ -145,15 +149,16 @@ where
145149
F: Interceptor,
146150
S: Service<http::Request<ReqBody>, Response = http::Response<ResBody>>,
147151
S::Error: Into<crate::Error>,
152+
ResBody: http_body::Body<Data = bytes::Bytes> + Send + 'static,
148153
ResBody::Error: Into<crate::Error>,
149154
{
150-
type Response = http::Response<ResBody>;
151-
type Error = crate::Error;
155+
type Response = http::Response<BoxBody>;
156+
type Error = S::Error;
152157
type Future = ResponseFuture<S::Future>;
153158

154159
#[inline]
155160
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
156-
self.inner.poll_ready(cx).map_err(Into::into)
161+
self.inner.poll_ready(cx)
157162
}
158163

159164
fn call(&mut self, req: http::Request<ReqBody>) -> Self::Future {
@@ -171,7 +176,7 @@ where
171176
let req = req.into_http(uri, SanitizeHeaders::No);
172177
ResponseFuture::future(self.inner.call(req))
173178
}
174-
Err(status) => ResponseFuture::error(status),
179+
Err(status) => ResponseFuture::status(status),
175180
}
176181
}
177182
}
@@ -200,9 +205,9 @@ impl<F> ResponseFuture<F> {
200205
}
201206
}
202207

203-
fn error(status: Status) -> Self {
208+
fn status(status: Status) -> Self {
204209
Self {
205-
kind: Kind::Error(Some(status)),
210+
kind: Kind::Status(Some(status)),
206211
}
207212
}
208213
}
@@ -211,7 +216,7 @@ impl<F> ResponseFuture<F> {
211216
#[derive(Debug)]
212217
enum Kind<F> {
213218
Future(#[pin] F),
214-
Error(Option<Status>),
219+
Status(Option<Status>),
215220
}
216221

217222
impl<F, E, B> Future for ResponseFuture<F>
@@ -221,14 +226,20 @@ where
221226
B: Default + http_body::Body<Data = Bytes> + Send + 'static,
222227
B::Error: Into<crate::Error>,
223228
{
224-
type Output = Result<http::Response<B>, crate::Error>;
229+
type Output = Result<http::Response<BoxBody>, E>;
225230

226231
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
227232
match self.project().kind.project() {
228-
KindProj::Future(future) => future.poll(cx).map_err(Into::into),
229-
KindProj::Error(status) => {
230-
let response = status.take().unwrap().to_http().map(|_| B::default());
231-
233+
KindProj::Future(future) => future
234+
.poll(cx)
235+
.map(|result| result.map(|res| res.map(boxed))),
236+
KindProj::Status(status) => {
237+
let response = status
238+
.take()
239+
.unwrap()
240+
.to_http()
241+
.map(|_| B::default())
242+
.map(boxed);
232243
Poll::Ready(Ok(response))
233244
}
234245
}

0 commit comments

Comments
 (0)