lxy 0.1.1

A convenient async http and RPC framework in Rust
Documentation
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;

use bytes::Bytes;
use http::{Request, Response};
use http_body::Body as HttpBody;
use tonic::body::Body;
use tonic::service::Routes;
use tonic::transport::Server;
use tower::{Layer, Service};

use super::GrpcConfig;
use crate::tracing::info;

pub(crate) struct GrpcServer<T> {
  server: Server<T>,
  routes: Routes,
  config: Arc<GrpcConfig>,
}

impl<T> GrpcServer<T> {
  pub fn new(server: Server<T>, routes: Routes, config: Arc<GrpcConfig>) -> Self {
    Self {
      server,
      routes,
      config,
    }
  }
}

impl<L, ResBody> crate::server::Server for GrpcServer<L>
where
  L: Layer<Routes> + Clone + Send + 'static,
  L::Service: Service<Request<Body>, Response = Response<ResBody>> + Clone + Send + 'static,
  <<L as Layer<Routes>>::Service as Service<Request<Body>>>::Future: Send,
  <<L as Layer<Routes>>::Service as Service<Request<Body>>>::Error:
    Into<Box<dyn std::error::Error + Send + Sync>> + Send,
  ResBody: HttpBody<Data = Bytes> + Send + 'static,
  ResBody::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
{
  type Future = Pin<Box<dyn Future<Output = ()> + Send>>;

  fn start(&self) -> Self::Future {
    let mut server = self.server.clone();
    let routes = self.routes.clone();
    let config = self.config.clone();

    Box::pin(async move {
      let addr = format!("{}:{}", config.host, config.port)
        .parse()
        .expect("Invalid gRPC server address");

      info!("gRPC server listening on {}", addr);

      server
        .add_routes(routes)
        .serve(addr)
        .await
        .expect("gRPC server error");
    })
  }
}