Skip to content
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

volo-grpc和volo-http的中间件不知是否通用,是否支持动态加载 #472

Open
tgy3300 opened this issue Jul 17, 2024 · 2 comments

Comments

@tgy3300
Copy link

tgy3300 commented Jul 17, 2024

先说问题:

问题1:http服务能使用开发的测试中间件TestLayer和DemoLayer,但是grpc服务不能,所以一问:volo_grpc和volo_http的中间件是否通用

问题2:开发的测试中间件TestLayer和DemoLayer能否放在一个Vec中,如果能,哪这个Vec的类型如何定义,如下:

let mut layer_data = Vec::new();    //这里的变量类型如何定义
layer_data.push(TestLayer::new());
layer_data.push(DemoLayer::new());

volo-grpc和volo-http的中间件不知是否通用
下面是开发的测试中间件

//-----DemoLayer--------
use motore::{layer::Layer, service::Service};
use volo_http::{
    context::ServerContext, request::ServerRequest, response::ServerResponse, server::IntoResponse,
};

#[derive(Debug, Clone)]
pub struct DemoLayer;

impl DemoLayer {
    pub fn new() -> Self {
        Self
    }
}

impl<S> Layer<S> for DemoLayer {
    type Service = Demo<S>;

    fn layer(self, inner: S) -> Self::Service {
        println!("-----demo layer-----");
        Self::Service::new(inner)
    }
}

#[derive(Debug, Clone)]
pub struct Demo<S> {
    inner: S,
}

impl<S> Demo<S> {
    pub fn new(inner: S) -> Self {
        Self { inner }
    }
}

impl<S> Service<ServerContext, ServerRequest> for Demo<S>
where
    S: Service<ServerContext, ServerRequest> + Send + Sync + 'static,
    S::Response: IntoResponse,
    S::Error: IntoResponse,
{
    type Response = ServerResponse;
    type Error = S::Error;

    async fn call(
        &self,
        cx: &mut ServerContext,
        req: ServerRequest,
    ) -> Result<Self::Response, Self::Error> {
        println!("-----demo call-----");
        Ok(self.inner.call(cx, req).await.into_response())
    }
}
//-----TestLayer--------
use motore::{layer::Layer, service::Service};
use volo_http::{
    context::ServerContext, request::ServerRequest, response::ServerResponse, server::IntoResponse,
};

#[derive(Debug, Clone)]
pub struct TestLayer;

impl TestLayer {
    pub fn new() -> Self {
        Self
    }
}

impl<S> Layer<S> for TestLayer {
    type Service = Test<S>;

    fn layer(self, inner: S) -> Self::Service {
        println!("-----test layer-----");
        Self::Service::new(inner)
    }
}

#[derive(Debug, Clone)]
pub struct Test<S> {
    inner: S,
}

impl<S> Test<S> {
    pub fn new(inner: S) -> Self {
        Self { inner }
    }
}

impl<S> Service<ServerContext, ServerRequest> for Test<S>
where
    S: Service<ServerContext, ServerRequest> + Send + Sync + 'static,
    S::Response: IntoResponse,
    S::Error: IntoResponse,
{
    type Response = ServerResponse;
    type Error = S::Error;

    async fn call(
        &self,
        cx: &mut ServerContext,
        req: ServerRequest,
    ) -> Result<Self::Response, Self::Error> {
        println!("-----test call-----");
        Ok(self.inner.call(cx, req).await.into_response())
    }
}

http 服务启动(正常)

use volo_http::{Router, Server as HttpServer}

let http_app = Router::new().route("xxx", get(xx)).route("xxx", get(xx)).layer(TestLayer::new()).layer(DemoLayer::new());
let addr: SocketAddr = "0.0.0.0:8080".parse().unwrap();
let addr = volo::net::Address::from(addr);
HttpServer::new(app).run(addr).await.unwrap();

grpc 服务启动(问题,中间件不通用)

use volo_grpc::server::Server as GrpcServer;

let addr: SocketAddr = "[::]:8080".parse().unwrap();
let addr = volo::net::Address::from(addr);
GrpcServer::new().add_service(s).layer(TestLayer::new()).layer(DemoLayer::new()).run(addr).await.unwrap();
@PureWhiteWu
Copy link
Member

抱歉回复有一些晚。

Service 中间件是否通用主要看的是你是否对 Cx 及 Req 有明确的要求或者指定。

比如,如果你一定需要从 Cx 中获取一些 HTTP 的信息,那么你就需要指定 Cx 为 Volo-HTTP 的 Context 了,这种情况下中间件就不能复用了。

但是如果你直接使用 Volo 的 Context 就能满足需求,那么就是可以通用的,Volo-HTTP 和 Volo-gRPC 的 Context 都是基于 Volo 的 Context 扩展得到的。

@Millione
Copy link
Member

问题2: 两个不同类型是不能放到一个Vec里的,如果你一定要放在一个Vec里,需要加一层Box擦除具体类型

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants