Skip to content

Instantly share code, notes, and snippets.

@afpro
Last active November 14, 2023 04:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save afpro/149c598ade2ad7f2466e0e0c40a55f19 to your computer and use it in GitHub Desktop.
Save afpro/149c598ade2ad7f2466e0e0c40a55f19 to your computer and use it in GitHub Desktop.
serve tonic service on axum
use std::{convert::Infallible, error::Error};
#[cfg(feature = "reflection")]
use anyhow::{Context, Result};
use axum::{
body::Body,
http::{Request, Response},
Router,
};
use tonic::{body::BoxBody, server::NamedService};
use tower::{Service, ServiceExt};
pub trait TonicAxum: Sized {
fn add_tonic_service<S>(self, service: S) -> Self
where
S: Service<Request<Body>, Response = Response<BoxBody>, Error = Infallible>
+ NamedService
+ Clone
+ Send
+ 'static,
S::Future: Send + 'static,
S::Error: Into<Box<dyn Error + Send + Sync>> + Send;
#[cfg(feature = "reflection")]
fn add_tonic_reflection(self, desc_list: &[&[u8]]) -> Result<Self> {
let mut service = tonic_reflection::server::Builder::configure();
for desc in desc_list {
service = service.register_encoded_file_descriptor_set(desc);
}
let service = service.build().context("generate tonic reflect service")?;
Ok(self.add_tonic_service(service))
}
}
impl TonicAxum for Router {
fn add_tonic_service<S>(self, service: S) -> Self
where
S: Service<Request<Body>, Response = Response<BoxBody>, Error = Infallible>
+ NamedService
+ Clone
+ Send
+ 'static,
S::Future: Send + 'static,
S::Error: Into<Box<dyn Error + Send + Sync>> + Send,
{
self.route_service(
&format!("/{}/*rest", S::NAME),
service.map_response(|resp| resp.map(axum::body::boxed)),
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment