From dcb882d20f11dfbde5c1d912807cf9fd10df7968 Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Thu, 3 Aug 2023 11:27:55 -0400 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81curl=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E8=AE=BF=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将json消息转化为grpc消息,继而交给grpc handle进行处理,并以json格式返回数据 --- Cargo.toml | 3 +- dubbo-build/Cargo.toml | 4 +- dubbo-build/src/prost.rs | 2 + dubbo-build/src/server.rs | 34 ++- dubbo/Cargo.toml | 2 +- dubbo/src/codegen.rs | 2 +- dubbo/src/triple/decode_json.rs | 136 +++++++++++ dubbo/src/triple/encode_json.rs | 70 ++++++ dubbo/src/triple/mod.rs | 2 + dubbo/src/triple/server/triple.rs | 38 +++ examples/echo/Cargo.toml | 7 +- examples/echo/src/example.http | 7 + .../echo/src/generated/grpc.examples.echo.rs | 220 ++++++++++++------ examples/greeter/Cargo.toml | 7 +- examples/greeter/src/example.http | 8 + 15 files changed, 450 insertions(+), 92 deletions(-) create mode 100644 dubbo/src/triple/decode_json.rs create mode 100644 dubbo/src/triple/encode_json.rs create mode 100644 examples/echo/src/example.http create mode 100644 examples/greeter/src/example.http diff --git a/Cargo.toml b/Cargo.toml index 5270ba42..ad39f084 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,6 +57,7 @@ serde_yaml = "0.9.4" # yaml file parser once_cell = "1.16.0" itertools = "0.10.1" bytes = "1.0" - +prost-serde = "0.3.0" +prost-serde-derive = "0.1.2" diff --git a/dubbo-build/Cargo.toml b/dubbo-build/Cargo.toml index 3276a683..1ca031da 100644 --- a/dubbo-build/Cargo.toml +++ b/dubbo-build/Cargo.toml @@ -10,9 +10,9 @@ repository = "https://github.com/apache/dubbo-rust.git" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -prost = "0.11.0" +prost = "0.11.9" prettyplease = {version = "0.1"} proc-macro2 = "1.0" quote = "1.0" syn = "1.0" -prost-build = "0.11.1" +prost-build = "0.11.9" diff --git a/dubbo-build/src/prost.rs b/dubbo-build/src/prost.rs index 3918fd30..1cd92f66 100644 --- a/dubbo-build/src/prost.rs +++ b/dubbo-build/src/prost.rs @@ -93,6 +93,8 @@ impl Builder { PathBuf::from(std::env::var("OUT_DIR").unwrap()) }; config.out_dir(out_dir); + config.type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize)]"); + config.type_attribute(".", "#[serde(default)]"); if self.compile_well_known_types { config.compile_well_known_types(); diff --git a/dubbo-build/src/server.rs b/dubbo-build/src/server.rs index 4dbbc9d2..b6088b96 100644 --- a/dubbo-build/src/server.rs +++ b/dubbo-build/src/server.rs @@ -330,7 +330,7 @@ fn generate_unary( method_ident: Ident, server_trait: Ident, ) -> TokenStream { - let codec_name = syn::parse_str::(CODEC_PATH).unwrap(); + // let codec_name = syn::parse_str::(CODEC_PATH).unwrap(); let service_ident = quote::format_ident!("{}Server", method.identifier()); @@ -355,16 +355,28 @@ fn generate_unary( } } - let fut = async move { - let mut server = TripleServer::new( - #codec_name::<#response, #request>::default() - ); - - let res = server.unary(#service_ident { inner }, req).await; - Ok(res) - }; - - Box::pin(fut) + let content_type= req.headers().get("content-type").unwrap().to_str().unwrap(); + if content_type == "application/json" { + let codec = dubbo::codegen::SerdeCodec::< + #response, #request + >::default(); + let fut = async move { + let mut server = TripleServer::new(codec); + let res = server.unary_for_curl(#service_ident { inner }, req).await; + Ok(res) + }; + Box::pin(fut) + } else { + let codec = dubbo::codegen::ProstCodec::< + #response, #request + >::default(); + let fut = async move { + let mut server = TripleServer::new(codec); + let res = server.unary(#service_ident { inner }, req).await; + Ok(res) + }; + Box::pin(fut) + } } } diff --git a/dubbo/Cargo.toml b/dubbo/Cargo.toml index d0ab2a4d..f51523d7 100644 --- a/dubbo/Cargo.toml +++ b/dubbo/Cargo.toml @@ -21,7 +21,7 @@ argh = "0.1" rustls-pemfile = "1.0.0" tokio-rustls="0.23.4" tokio = { version = "1.0", features = [ "rt-multi-thread", "time", "fs", "macros", "net", "signal", "full" ] } -prost = "0.10.4" +prost = "0.11.9" async-trait = "0.1.56" tower-layer.workspace = true bytes.workspace = true diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index 412feb91..aaabb438 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -34,7 +34,7 @@ pub use super::{ registry::{BoxRegistry, Registry}, triple::{ client::TripleClient, - codec::{prost::ProstCodec, Codec}, + codec::{prost::ProstCodec, serde_codec::SerdeCodec,Codec}, decode::Decoding, server::{ service::{ClientStreamingSvc, ServerStreamingSvc, StreamingSvc, UnarySvc}, diff --git a/dubbo/src/triple/decode_json.rs b/dubbo/src/triple/decode_json.rs new file mode 100644 index 00000000..0106d562 --- /dev/null +++ b/dubbo/src/triple/decode_json.rs @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use std::{pin::Pin, task::Poll}; + +use bytes::{Buf, BufMut, Bytes, BytesMut}; +use futures_util::{ ready, Stream}; +use http_body::Body; +use crate::{ + triple::codec::{DecodeBuf, Decoder}, +}; + +type BoxBody = http_body::combinators::UnsyncBoxBody; + +pub struct DecodingJSON { + state: State, + body: BoxBody, + decoder: Box + Send + 'static>, + buf: BytesMut, + // decompress_buf: BytesMut, +} + +#[derive(PartialEq)] +enum State { + Prepare, + ReadBody, + Ok, + Error, +} + +impl DecodingJSON { + pub fn new(body: B, decoder: D) -> Self + where + B: Body + Send + 'static, + B::Error: Into, + D: Decoder + Send + 'static, + { + Self { + state: State::Prepare, + body: body + .map_data(|mut buf| buf.copy_to_bytes(buf.remaining())) + .map_err(|_err| { + crate::status::Status::new( + crate::status::Code::Internal, + "internal decode err".to_string(), + ) + }) + .boxed_unsync(), + decoder: Box::new(decoder), + buf: BytesMut::with_capacity(super::consts::BUFFER_SIZE), + // decompress_buf: BytesMut::new(), + } + } + + + pub fn decode_chunk(&mut self) -> Result, crate::status::Status> { + if self.state == State::Prepare { + self.state = State::ReadBody; + return Ok(None) + } + + if let State::ReadBody = self.state { + let decoding_result =self.decoder.decode(&mut DecodeBuf::new(&mut self.buf, super::consts::BUFFER_SIZE)); + + return match decoding_result { + Ok(Some(r)) => { + self.state = State::Ok; + Ok(Some(r)) + } + Ok(None) => Ok(None), + Err(err) => Err(err), + }; + } + + Ok(None) + } +} + +impl Stream for DecodingJSON { + type Item = Result; + + fn poll_next( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + loop { + if self.state == State::Error { + return Poll::Ready(None); + } + + if let Some(item) = self.decode_chunk()? { + return Poll::Ready(Some(Ok(item))); + } + + let chunk = match ready!(Pin::new(&mut self.body).poll_data(cx)) { + Some(Ok(d)) => Some(d), + Some(Err(e)) => { + let _ = std::mem::replace(&mut self.state, State::Error); + let err: crate::Error = e.into(); + return Poll::Ready(Some(Err(crate::status::Status::new( + crate::status::Code::Internal, + err.to_string(), + )))); + } + None => None, + }; + + if let Some(data) = chunk { + self.buf.put(data) + } else { + break; + } + } + + + Poll::Ready(None) + } + + fn size_hint(&self) -> (usize, Option) { + (0, None) + } +} diff --git a/dubbo/src/triple/encode_json.rs b/dubbo/src/triple/encode_json.rs new file mode 100644 index 00000000..2d2ab507 --- /dev/null +++ b/dubbo/src/triple/encode_json.rs @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +use crate::status::Status; +use bytes::{ Bytes, BytesMut}; +use futures_core::{Stream, TryStream}; +use futures_util::{ StreamExt, TryStreamExt}; + +use crate::triple::codec::{EncodeBuf, Encoder}; +use crate::triple::encode::EncodeBody; + +#[allow(unused_must_use)] +pub fn encode_json( + mut encoder: E, + resp_body: B, +) -> impl TryStream + where + E: Encoder, + B: Stream>, +{ + async_stream::stream! { + let mut buf = BytesMut::with_capacity(super::consts::BUFFER_SIZE); + futures_util::pin_mut!(resp_body); + + loop { + match resp_body.next().await { + Some(Ok(item)) => { + match encoder.encode(item, &mut EncodeBuf::new(&mut buf)) { + Ok(_) => { + yield Ok(buf.clone().freeze()); + buf.clear(); + }, + Err(e) => { + yield Err(crate::status::Status::new(crate::status::Code::Internal, format!("encode error: {}", e))); + break; + } + } + }, + Some(Err(err)) => yield Err(err.into()), + None => break, + } + } + } +} + +pub fn encode_server_json( + encoder: E, + body: B, +) -> EncodeBody>> + where + E: Encoder, + B: Stream>, +{ + let s = encode_json(encoder, body).into_stream(); + EncodeBody::new_server(s) +} + diff --git a/dubbo/src/triple/mod.rs b/dubbo/src/triple/mod.rs index 799ac099..a2c85ed1 100644 --- a/dubbo/src/triple/mod.rs +++ b/dubbo/src/triple/mod.rs @@ -23,3 +23,5 @@ pub mod decode; pub mod encode; pub mod server; pub mod transport; +mod decode_json; +mod encode_json; diff --git a/dubbo/src/triple/server/triple.rs b/dubbo/src/triple/server/triple.rs index 2c0626ce..e151e98e 100644 --- a/dubbo/src/triple/server/triple.rs +++ b/dubbo/src/triple/server/triple.rs @@ -30,6 +30,8 @@ use crate::{ BoxBody, }; use dubbo_config::BusinessConfig; +use crate::triple::decode_json::DecodingJSON; +use crate::triple::encode_json::encode_server_json; pub const GRPC_ACCEPT_ENCODING: &str = "grpc-accept-encoding"; pub const GRPC_ENCODING: &str = "grpc-encoding"; @@ -258,6 +260,42 @@ where http::Response::from_parts(parts, BoxBody::new(resp_body)) } + pub async fn unary_for_curl( + &mut self, + mut service: S, + req: http::Request, + ) -> http::Response + where + S: UnarySvc, + B: Body + Send + 'static, + B::Error: Into + Send, + { + let req_stream = req.map(|body| DecodingJSON::new(body, self.codec.decoder())); + let (parts, mut body) = Request::from_http(req_stream).into_parts(); + let msg = body.try_next().await.unwrap().ok_or_else(|| { + crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) + }); + let msg = match msg { + Ok(v) => v, + Err(err) => return err.to_http(), + }; + let resp = service.call(Request::from_parts(parts, msg)).await; + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + let resp_body = encode_server_json( + self.codec.encoder(), + stream::once(future::ready(resp_body)).map(Ok).into_stream(), + ); + parts.headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/json"), + ); + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) + } + fn get_encoding_from_req( &self, header: &http::HeaderMap, diff --git a/examples/echo/Cargo.toml b/examples/echo/Cargo.toml index bc6638b8..81df8edf 100644 --- a/examples/echo/Cargo.toml +++ b/examples/echo/Cargo.toml @@ -24,8 +24,11 @@ http = "0.2" http-body = "0.4.4" futures-util = {version = "0.3", default-features = false} tokio = { version = "1.0", features = [ "rt-multi-thread", "time", "fs", "macros", "net", "signal"] } -prost-derive = {version = "0.10", optional = true} -prost = "0.10.4" +prost-derive = {version = "0.11.9", optional = true} +prost = "0.11.9" +prost-serde = "0.3.0" +prost-serde-derive = "0.1.2" +serde = { version = "1.0.171",features = ["derive"] } async-trait = "0.1.56" tokio-stream = "0.1" dubbo-logger.workspace=true diff --git a/examples/echo/src/example.http b/examples/echo/src/example.http new file mode 100644 index 00000000..8a54d96e --- /dev/null +++ b/examples/echo/src/example.http @@ -0,0 +1,7 @@ +POST /grpc.examples.echo.Echo/UnaryEcho HTTP/1.1 +Host: 127.0.0.1:8888 +Content-Type: application/json + +{ + "message":"1" +} diff --git a/examples/echo/src/generated/grpc.examples.echo.rs b/examples/echo/src/generated/grpc.examples.echo.rs index 16fb1638..3d90d9a9 100644 --- a/examples/echo/src/generated/grpc.examples.echo.rs +++ b/examples/echo/src/generated/grpc.examples.echo.rs @@ -1,12 +1,16 @@ -// @generated by apache/dubbo-rust. - /// EchoRequest is the request for echo. +#[derive(serde::Serialize, serde::Deserialize)] +#[serde(default)] +#[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct EchoRequest { #[prost(string, tag = "1")] pub message: ::prost::alloc::string::String, } /// EchoResponse is the response for echo. +#[derive(serde::Serialize, serde::Deserialize)] +#[serde(default)] +#[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct EchoResponse { #[prost(string, tag = "1")] @@ -31,21 +35,21 @@ pub mod echo_client { inner: TripleClient::new(builder), } } - pub fn with_cluster(mut self, invoker: ClusterInvoker) -> Self { - self.inner = self.inner.with_cluster(invoker); - self - } /// UnaryEcho is unary echo. pub async fn unary_echo( &mut self, request: Request, ) -> Result, dubbo::status::Status> { - let codec = - dubbo::codegen::ProstCodec::::default(); + let codec = dubbo::codegen::ProstCodec::< + super::EchoRequest, + super::EchoResponse, + >::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("UnaryEcho")); - let path = http::uri::PathAndQuery::from_static("/grpc.examples.echo.Echo/UnaryEcho"); + let path = http::uri::PathAndQuery::from_static( + "/grpc.examples.echo.Echo/UnaryEcho", + ); self.inner.unary(request, codec, path, invocation).await } /// ServerStreamingEcho is server side streaming. @@ -53,51 +57,51 @@ pub mod echo_client { &mut self, request: Request, ) -> Result>, dubbo::status::Status> { - let codec = - dubbo::codegen::ProstCodec::::default(); + let codec = dubbo::codegen::ProstCodec::< + super::EchoRequest, + super::EchoResponse, + >::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("ServerStreamingEcho")); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/ServerStreamingEcho", ); - self.inner - .server_streaming(request, codec, path, invocation) - .await + self.inner.server_streaming(request, codec, path, invocation).await } /// ClientStreamingEcho is client side streaming. pub async fn client_streaming_echo( &mut self, request: impl IntoStreamingRequest, ) -> Result, dubbo::status::Status> { - let codec = - dubbo::codegen::ProstCodec::::default(); + let codec = dubbo::codegen::ProstCodec::< + super::EchoRequest, + super::EchoResponse, + >::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("ClientStreamingEcho")); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/ClientStreamingEcho", ); - self.inner - .client_streaming(request, codec, path, invocation) - .await + self.inner.client_streaming(request, codec, path, invocation).await } /// BidirectionalStreamingEcho is bidi streaming. pub async fn bidirectional_streaming_echo( &mut self, request: impl IntoStreamingRequest, ) -> Result>, dubbo::status::Status> { - let codec = - dubbo::codegen::ProstCodec::::default(); + let codec = dubbo::codegen::ProstCodec::< + super::EchoRequest, + super::EchoResponse, + >::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("BidirectionalStreamingEcho")); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/BidirectionalStreamingEcho", ); - self.inner - .bidi_streaming(request, codec, path, invocation) - .await + self.inner.bidi_streaming(request, codec, path, invocation).await } } } @@ -114,7 +118,9 @@ pub mod echo_server { request: Request, ) -> Result, dubbo::status::Status>; ///Server streaming response type for the ServerStreamingEcho method. - type ServerStreamingEchoStream: futures_util::Stream> + type ServerStreamingEchoStream: futures_util::Stream< + Item = Result, + > + Send + 'static; /// ServerStreamingEcho is server side streaming. @@ -128,14 +134,19 @@ pub mod echo_server { request: Request>, ) -> Result, dubbo::status::Status>; ///Server streaming response type for the BidirectionalStreamingEcho method. - type BidirectionalStreamingEchoStream: futures_util::Stream> + type BidirectionalStreamingEchoStream: futures_util::Stream< + Item = Result, + > + Send + 'static; /// BidirectionalStreamingEcho is bidi streaming. async fn bidirectional_streaming_echo( &self, request: Request>, - ) -> Result, dubbo::status::Status>; + ) -> Result< + Response, + dubbo::status::Status, + >; } /// Echo is the echo service. #[derive(Debug)] @@ -165,7 +176,10 @@ pub mod echo_server { type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; - fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { Poll::Ready(Ok(())) } fn call(&mut self, req: http::Request) -> Self::Future { @@ -178,44 +192,82 @@ pub mod echo_server { } impl UnarySvc for UnaryEchoServer { type Response = super::EchoResponse; - type Future = BoxFuture, dubbo::status::Status>; - fn call(&mut self, request: Request) -> Self::Future { + type Future = BoxFuture< + Response, + dubbo::status::Status, + >; + fn call( + &mut self, + request: Request, + ) -> Self::Future { let inner = self.inner.0.clone(); let fut = async move { inner.unary_echo(request).await }; Box::pin(fut) } } - let fut = async move { - let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< + let content_type = req + .headers() + .get("content-type") + .unwrap() + .to_str() + .unwrap(); + if content_type == "application/json" { + let codec = dubbo::codegen::SerdeCodec::< super::EchoResponse, super::EchoRequest, - >::default()); - let res = server.unary(UnaryEchoServer { inner }, req).await; - Ok(res) - }; - Box::pin(fut) + >::default(); + let fut = async move { + let mut server = TripleServer::new(codec); + let res = server + .unary_for_curl(UnaryEchoServer { inner }, req) + .await; + Ok(res) + }; + Box::pin(fut) + } else { + let codec = dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default(); + let fut = async move { + let mut server = TripleServer::new(codec); + let res = server.unary(UnaryEchoServer { inner }, req).await; + Ok(res) + }; + Box::pin(fut) + } } "/grpc.examples.echo.Echo/ServerStreamingEcho" => { #[allow(non_camel_case_types)] struct ServerStreamingEchoServer { inner: _Inner, } - impl ServerStreamingSvc for ServerStreamingEchoServer { + impl ServerStreamingSvc + for ServerStreamingEchoServer { type Response = super::EchoResponse; type ResponseStream = T::ServerStreamingEchoStream; - type Future = - BoxFuture, dubbo::status::Status>; - fn call(&mut self, request: Request) -> Self::Future { + type Future = BoxFuture< + Response, + dubbo::status::Status, + >; + fn call( + &mut self, + request: Request, + ) -> Self::Future { let inner = self.inner.0.clone(); - let fut = async move { inner.server_streaming_echo(request).await }; + let fut = async move { + inner.server_streaming_echo(request).await + }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default()); + let mut server = TripleServer::new( + dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default(), + ); let res = server .server_streaming(ServerStreamingEchoServer { inner }, req) .await; @@ -228,23 +280,32 @@ pub mod echo_server { struct ClientStreamingEchoServer { inner: _Inner, } - impl ClientStreamingSvc for ClientStreamingEchoServer { + impl ClientStreamingSvc + for ClientStreamingEchoServer { type Response = super::EchoResponse; - type Future = BoxFuture, dubbo::status::Status>; + type Future = BoxFuture< + Response, + dubbo::status::Status, + >; fn call( &mut self, request: Request>, - ) -> Self::Future { + ) -> Self::Future {prost-serde = "0.3.0" +prost-serde-derive = "0.1.2" let inner = self.inner.0.clone(); - let fut = async move { inner.client_streaming_echo(request).await }; + let fut = async move { + inner.client_streaming_echo(request).await + }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default()); + let mut server = TripleServer::new( + dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default(), + ); let res = server .client_streaming(ClientStreamingEchoServer { inner }, req) .await; @@ -257,41 +318,56 @@ pub mod echo_server { struct BidirectionalStreamingEchoServer { inner: _Inner, } - impl StreamingSvc for BidirectionalStreamingEchoServer { + impl StreamingSvc + for BidirectionalStreamingEchoServer { type Response = super::EchoResponse; type ResponseStream = T::BidirectionalStreamingEchoStream; - type Future = - BoxFuture, dubbo::status::Status>; + type Future = BoxFuture< + Response, + dubbo::status::Status, + >; fn call( &mut self, request: Request>, ) -> Self::Future { let inner = self.inner.0.clone(); - let fut = - async move { inner.bidirectional_streaming_echo(request).await }; + let fut = async move { + inner.bidirectional_streaming_echo(request).await + }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::new(dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default()); + let mut server = TripleServer::new( + dubbo::codegen::ProstCodec::< + super::EchoResponse, + super::EchoRequest, + >::default(), + ); let res = server - .bidi_streaming(BidirectionalStreamingEchoServer { inner }, req) + .bidi_streaming( + BidirectionalStreamingEchoServer { + inner, + }, + req, + ) .await; Ok(res) }; Box::pin(fut) } - _ => Box::pin(async move { - Ok(http::Response::builder() - .status(200) - .header("grpc-status", "12") - .header("content-type", "application/grpc") - .body(empty_body()) - .unwrap()) - }), + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } } } } diff --git a/examples/greeter/Cargo.toml b/examples/greeter/Cargo.toml index d68cab7b..37faf91a 100644 --- a/examples/greeter/Cargo.toml +++ b/examples/greeter/Cargo.toml @@ -24,8 +24,11 @@ http = "0.2" http-body = "0.4.4" futures-util = { version = "0.3", default-features = false } tokio = { version = "1.0", features = ["rt-multi-thread", "time", "fs", "macros", "net", "signal"] } -prost-derive = { version = "0.10", optional = true } -prost = "0.10.4" +prost-derive = { version = "0.11.9", optional = true } +prost = "0.11.9" +serde = { version = "1.0.171",features = ["derive"] } +prost-serde = "0.3.0" +prost-serde-derive = "0.1.2" async-trait = "0.1.56" tokio-stream = "0.1" dubbo-logger = { path = "../../common/logger" } diff --git a/examples/greeter/src/example.http b/examples/greeter/src/example.http new file mode 100644 index 00000000..e7255cfd --- /dev/null +++ b/examples/greeter/src/example.http @@ -0,0 +1,8 @@ +POST /org.apache.dubbo.sample.tri.Greeter/greet HTTP/1.1 +Host: 127.0.0.1:8888 +Content-Type: application/json + +{ + "message":"hello,你好" +} + From dfa26070ac5a9f26a9890d0117098b09f2107023 Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Sun, 6 Aug 2023 20:13:10 -0400 Subject: [PATCH 02/11] fix(fix bug): --- examples/echo/src/generated/grpc.examples.echo.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/echo/src/generated/grpc.examples.echo.rs b/examples/echo/src/generated/grpc.examples.echo.rs index 3d90d9a9..e4c989f6 100644 --- a/examples/echo/src/generated/grpc.examples.echo.rs +++ b/examples/echo/src/generated/grpc.examples.echo.rs @@ -290,8 +290,7 @@ pub mod echo_server { fn call( &mut self, request: Request>, - ) -> Self::Future {prost-serde = "0.3.0" -prost-serde-derive = "0.1.2" + ) -> Self::Future { let inner = self.inner.0.clone(); let fut = async move { inner.client_streaming_echo(request).await From cd7fdce3bbe5cc1fbfe7043a11a2f5a3b2b9c05d Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Wed, 9 Aug 2023 17:03:51 -0400 Subject: [PATCH 03/11] =?UTF-8?q?refactor:=20=E5=B0=86=E7=94=9F=E6=88=90Co?= =?UTF-8?q?dec=E7=9A=84=E9=80=BB=E8=BE=91=E8=BD=AC=E7=A7=BB=E5=88=B0?= =?UTF-8?q?=E4=BA=86TripleServer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dubbo-build/src/server.rs | 52 ++--- dubbo/src/triple/decode_json.rs | 1 - dubbo/src/triple/server/triple.rs | 216 +++++++++--------- .../echo/src/generated/grpc.examples.echo.rs | 66 ++---- 4 files changed, 139 insertions(+), 196 deletions(-) diff --git a/dubbo-build/src/server.rs b/dubbo-build/src/server.rs index b6088b96..8b5f5a4c 100644 --- a/dubbo-build/src/server.rs +++ b/dubbo-build/src/server.rs @@ -336,6 +336,7 @@ fn generate_unary( let (request, response) = method.request_response_name(proto_path, compile_well_known_types); + quote! { #[allow(non_camel_case_types)] struct #service_ident { @@ -354,29 +355,12 @@ fn generate_unary( Box::pin(fut) } } - - let content_type= req.headers().get("content-type").unwrap().to_str().unwrap(); - if content_type == "application/json" { - let codec = dubbo::codegen::SerdeCodec::< - #response, #request - >::default(); - let fut = async move { - let mut server = TripleServer::new(codec); - let res = server.unary_for_curl(#service_ident { inner }, req).await; - Ok(res) - }; - Box::pin(fut) - } else { - let codec = dubbo::codegen::ProstCodec::< - #response, #request - >::default(); - let fut = async move { - let mut server = TripleServer::new(codec); - let res = server.unary(#service_ident { inner }, req).await; - Ok(res) - }; - Box::pin(fut) - } + let fut = async move { + let mut server = TripleServer::<#request,#response>::new(); + let res = server.unary(#service_ident { inner }, req).await; + Ok(res) + }; + Box::pin(fut) } } @@ -387,7 +371,7 @@ fn generate_server_streaming( method_ident: Ident, server_trait: Ident, ) -> TokenStream { - let codec_name = syn::parse_str::(CODEC_PATH).unwrap(); + let _codec_name = syn::parse_str::(CODEC_PATH).unwrap(); let service_ident = quote::format_ident!("{}Server", method.identifier()); @@ -414,12 +398,8 @@ fn generate_server_streaming( Box::pin(fut) } } - let fut = async move { - let mut server = TripleServer::new( - #codec_name::<#response, #request>::default() - ); - + let mut server = TripleServer::<#request,#response>::new(); let res = server.server_streaming(#service_ident { inner }, req).await; Ok(res) }; @@ -438,7 +418,7 @@ fn generate_client_streaming( let service_ident = quote::format_ident!("{}Server", method.identifier()); let (request, response) = method.request_response_name(proto_path, compile_well_known_types); - let codec_name = syn::parse_str::(CODEC_PATH).unwrap(); + let _codec_name = syn::parse_str::(CODEC_PATH).unwrap(); quote! { #[allow(non_camel_case_types)] @@ -462,10 +442,7 @@ fn generate_client_streaming( } let fut = async move { - let mut server = TripleServer::new( - #codec_name::<#response, #request>::default() - ); - + let mut server = TripleServer::<#request,#response>::new(); let res = server.client_streaming(#service_ident { inner }, req).await; Ok(res) }; @@ -481,7 +458,7 @@ fn generate_streaming( method_ident: Ident, server_trait: Ident, ) -> TokenStream { - let codec_name = syn::parse_str::(CODEC_PATH).unwrap(); + let _codec_name = syn::parse_str::(CODEC_PATH).unwrap(); let service_ident = quote::format_ident!("{}Server", method.identifier()); @@ -511,10 +488,7 @@ fn generate_streaming( } let fut = async move { - let mut server = TripleServer::new( - #codec_name::<#response, #request>::default() - ); - + let mut server = TripleServer::<#request,#response>::new(); let res = server.bidi_streaming(#service_ident { inner }, req).await; Ok(res) }; diff --git a/dubbo/src/triple/decode_json.rs b/dubbo/src/triple/decode_json.rs index 0106d562..beb07d5d 100644 --- a/dubbo/src/triple/decode_json.rs +++ b/dubbo/src/triple/decode_json.rs @@ -126,7 +126,6 @@ impl Stream for DecodingJSON { } } - Poll::Ready(None) } diff --git a/dubbo/src/triple/server/triple.rs b/dubbo/src/triple/server/triple.rs index e151e98e..a6d389f5 100644 --- a/dubbo/src/triple/server/triple.rs +++ b/dubbo/src/triple/server/triple.rs @@ -17,6 +17,8 @@ use futures_util::{future, stream, StreamExt, TryStreamExt}; use http_body::Body; +use prost::Message; +use serde::{Deserialize, Serialize}; use crate::{ invocation::Request, @@ -30,39 +32,44 @@ use crate::{ BoxBody, }; use dubbo_config::BusinessConfig; +use crate::codegen::{ProstCodec, SerdeCodec}; use crate::triple::decode_json::DecodingJSON; use crate::triple::encode_json::encode_server_json; pub const GRPC_ACCEPT_ENCODING: &str = "grpc-accept-encoding"; pub const GRPC_ENCODING: &str = "grpc-encoding"; -pub struct TripleServer { - codec: T, +pub struct TripleServer +{ + prost_codec: ProstCodec, + serde_codec: SerdeCodec, compression: Option, } -impl TripleServer { - pub fn new(codec: T) -> Self { +impl TripleServer { + pub fn new() -> Self { Self { - codec, + prost_codec: ProstCodec::default(), + serde_codec: SerdeCodec::default(), compression: None, } } } -impl TripleServer -where - T: Codec, +impl TripleServer + where + T: Message + for<'a> Deserialize<'a> + Default + 'static, + V: Message + Serialize + Default + 'static { pub async fn client_streaming( &mut self, mut service: S, req: http::Request, ) -> http::Response - where - S: ClientStreamingSvc, - B: Body + Send + 'static, - B::Error: Into + Send, + where + S: ClientStreamingSvc, + B: Body + Send + 'static, + B::Error: Into + Send, { let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); if self.compression.is_none() || accept_encoding.is_none() { @@ -75,7 +82,7 @@ where Err(status) => return status.to_http(), }; - let req_stream = req.map(|body| Decoding::new(body, self.codec.decoder(), compression)); + let req_stream = req.map(|body| Decoding::new(body, self.prost_codec.decoder(), compression)); let resp = service.call(Request::from_http(req_stream)).await; @@ -85,7 +92,7 @@ where }; let resp_body = encode_server( - self.codec.encoder(), + self.prost_codec.encoder(), stream::once(future::ready(resp_body)).map(Ok).into_stream(), accept_encoding, ); @@ -108,11 +115,11 @@ where mut service: S, req: http::Request, ) -> http::Response - where - S: StreamingSvc, - S::ResponseStream: Send + 'static, - B: Body + Send + 'static, - B::Error: Into + Send, + where + S: StreamingSvc, + S::ResponseStream: Send + 'static, + B: Body + Send + 'static, + B::Error: Into + Send, { // Firstly, get grpc_accept_encoding from http_header, get compression // Secondly, if server enable compression and compression is valid, this method should compress response @@ -127,7 +134,7 @@ where Err(status) => return status.to_http(), }; - let req_stream = req.map(|body| Decoding::new(body, self.codec.decoder(), compression)); + let req_stream = req.map(|body| Decoding::new(body, self.prost_codec.decoder(), compression)); let resp = service.call(Request::from_http(req_stream)).await; @@ -135,7 +142,7 @@ where Ok(v) => v.into_http().into_parts(), Err(err) => return err.to_http(), }; - let resp_body = encode_server(self.codec.encoder(), resp_body, compression); + let resp_body = encode_server(self.prost_codec.encoder(), resp_body, compression); parts.headers.insert( http::header::CONTENT_TYPE, @@ -155,11 +162,11 @@ where mut service: S, req: http::Request, ) -> http::Response - where - S: ServerStreamingSvc, - S::ResponseStream: Send + 'static, - B: Body + Send + 'static, - B::Error: Into + Send, + where + S: ServerStreamingSvc, + S::ResponseStream: Send + 'static, + B: Body + Send + 'static, + B::Error: Into + Send, { // Firstly, get grpc_accept_encoding from http_header, get compression // Secondly, if server enable compression and compression is valid, this method should compress response @@ -174,7 +181,7 @@ where Err(status) => return status.to_http(), }; - let req_stream = req.map(|body| Decoding::new(body, self.codec.decoder(), compression)); + let req_stream = req.map(|body| Decoding::new(body, self.prost_codec.decoder(), compression)); let (parts, mut body) = Request::from_http(req_stream).into_parts(); let msg = body.try_next().await.unwrap().ok_or_else(|| { crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) @@ -190,7 +197,7 @@ where Ok(v) => v.into_http().into_parts(), Err(err) => return err.to_http(), }; - let resp_body = encode_server(self.codec.encoder(), resp_body, compression); + let resp_body = encode_server(self.prost_codec.encoder(), resp_body, compression); parts.headers.insert( http::header::CONTENT_TYPE, @@ -209,91 +216,82 @@ where &mut self, mut service: S, req: http::Request, - ) -> http::Response - where - S: UnarySvc, - B: Body + Send + 'static, - B::Error: Into + Send, - { - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; - } - - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; - - let req_stream = req.map(|body| Decoding::new(body, self.codec.decoder(), compression)); - let (parts, mut body) = Request::from_http(req_stream).into_parts(); - let msg = body.try_next().await.unwrap().ok_or_else(|| { - crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) - }); - let msg = match msg { - Ok(v) => v, - Err(err) => return err.to_http(), - }; - - let resp = service.call(Request::from_parts(parts, msg)).await; - - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - let resp_body = encode_server( - self.codec.encoder(), - stream::once(future::ready(resp_body)).map(Ok).into_stream(), - accept_encoding, - ); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); - } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) - } - - pub async fn unary_for_curl( - &mut self, - mut service: S, - req: http::Request, ) -> http::Response where - S: UnarySvc, + S: UnarySvc, B: Body + Send + 'static, B::Error: Into + Send, { - let req_stream = req.map(|body| DecodingJSON::new(body, self.codec.decoder())); - let (parts, mut body) = Request::from_http(req_stream).into_parts(); - let msg = body.try_next().await.unwrap().ok_or_else(|| { - crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) - }); - let msg = match msg { - Ok(v) => v, - Err(err) => return err.to_http(), - }; - let resp = service.call(Request::from_parts(parts, msg)).await; - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - let resp_body = encode_server_json( - self.codec.encoder(), - stream::once(future::ready(resp_body)).map(Ok).into_stream(), - ); - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/json"), - ); - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) + if req.headers().get("content-type").unwrap() == "application/json" { + let req_stream = req.map(|body| DecodingJSON::new(body, self.serde_codec.decoder())); + let (parts, mut body) = Request::from_http(req_stream).into_parts(); + let msg = body.try_next().await.unwrap().ok_or_else(|| { + crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) + }); + let msg = match msg { + Ok(v) => v, + Err(err) => return err.to_http(), + }; + let resp = service.call(Request::from_parts(parts, msg)).await; + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + + let resp_body = encode_server_json( + self.serde_codec.encoder(), + stream::once(future::ready(resp_body)).map(Ok).into_stream(), + ); + parts.headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/json"), + ); + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) + } else { + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } + + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; + let req_stream = req.map(|body| Decoding::new(body, self.prost_codec.decoder(), compression)); + let (parts, mut body) = Request::from_http(req_stream).into_parts(); + let msg = body.try_next().await.unwrap().ok_or_else(|| { + crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) + }); + let msg = match msg { + Ok(v) => v, + Err(err) => return err.to_http(), + }; + + let resp = service.call(Request::from_parts(parts, msg)).await; + + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + let resp_body = encode_server( + self.prost_codec.encoder(), + stream::once(future::ready(resp_body)).map(Ok).into_stream(), + accept_encoding, + ); + + parts.headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/grpc"), + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); + } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) + } } fn get_encoding_from_req( @@ -320,7 +318,7 @@ where } } -impl BusinessConfig for TripleServer { +impl BusinessConfig for TripleServer { fn init() -> Self { todo!() } diff --git a/examples/echo/src/generated/grpc.examples.echo.rs b/examples/echo/src/generated/grpc.examples.echo.rs index e4c989f6..57a89cee 100644 --- a/examples/echo/src/generated/grpc.examples.echo.rs +++ b/examples/echo/src/generated/grpc.examples.echo.rs @@ -205,37 +205,15 @@ pub mod echo_server { Box::pin(fut) } } - let content_type = req - .headers() - .get("content-type") - .unwrap() - .to_str() - .unwrap(); - if content_type == "application/json" { - let codec = dubbo::codegen::SerdeCodec::< - super::EchoResponse, + let fut = async move { + let mut server = TripleServer::< super::EchoRequest, - >::default(); - let fut = async move { - let mut server = TripleServer::new(codec); - let res = server - .unary_for_curl(UnaryEchoServer { inner }, req) - .await; - Ok(res) - }; - Box::pin(fut) - } else { - let codec = dubbo::codegen::ProstCodec::< super::EchoResponse, - super::EchoRequest, - >::default(); - let fut = async move { - let mut server = TripleServer::new(codec); - let res = server.unary(UnaryEchoServer { inner }, req).await; - Ok(res) - }; - Box::pin(fut) - } + >::new(); + let res = server.unary(UnaryEchoServer { inner }, req).await; + Ok(res) + }; + Box::pin(fut) } "/grpc.examples.echo.Echo/ServerStreamingEcho" => { #[allow(non_camel_case_types)] @@ -262,12 +240,10 @@ pub mod echo_server { } } let fut = async move { - let mut server = TripleServer::new( - dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default(), - ); + let mut server = TripleServer::< + super::EchoRequest, + super::EchoResponse, + >::new(); let res = server .server_streaming(ServerStreamingEchoServer { inner }, req) .await; @@ -299,12 +275,10 @@ pub mod echo_server { } } let fut = async move { - let mut server = TripleServer::new( - dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default(), - ); + let mut server = TripleServer::< + super::EchoRequest, + super::EchoResponse, + >::new(); let res = server .client_streaming(ClientStreamingEchoServer { inner }, req) .await; @@ -337,12 +311,10 @@ pub mod echo_server { } } let fut = async move { - let mut server = TripleServer::new( - dubbo::codegen::ProstCodec::< - super::EchoResponse, - super::EchoRequest, - >::default(), - ); + let mut server = TripleServer::< + super::EchoRequest, + super::EchoResponse, + >::new(); let res = server .bidi_streaming( BidirectionalStreamingEchoServer { From fe963dc2b334586d31b1c09ade378aabd905a277 Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Sun, 13 Aug 2023 20:15:05 -0400 Subject: [PATCH 04/11] =?UTF-8?q?Feat:=20Added=20support=20for=20JSON=20en?= =?UTF-8?q?coding=20types=EF=BC=88#145=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application.yaml | 8 +- config/src/config.rs | 5 + config/src/consumer.rs | 41 ++ config/src/lib.rs | 1 + dubbo/src/triple/client/triple.rs | 654 +++++++++++++++++-------- dubbo/src/triple/decode.rs | 67 ++- dubbo/src/triple/decode_json.rs | 135 ----- dubbo/src/triple/encode.rs | 22 +- dubbo/src/triple/encode_json.rs | 39 +- dubbo/src/triple/mod.rs | 1 - dubbo/src/triple/server/triple.rs | 382 ++++++++++----- examples/echo/src/echo/client.rs | 19 +- examples/echo/src/example.http | 2 +- examples/greeter/src/example.http | 2 +- examples/greeter/src/greeter/server.rs | 2 +- 15 files changed, 883 insertions(+), 497 deletions(-) create mode 100644 config/src/consumer.rs delete mode 100644 dubbo/src/triple/decode_json.rs diff --git a/application.yaml b/application.yaml index d357db14..964484a2 100644 --- a/application.yaml +++ b/application.yaml @@ -19,6 +19,8 @@ dubbo: interface: org.apache.dubbo.sample.tri.Greeter consumer: references: - GreeterClientImpl: - url: tri://localhost:20000 - protocol: tri \ No newline at end of file + - url: tri://localhost:20000 + interface: org.apache.dubbo.sample.tri.Greeter + protocol: tri + coding: json + compress: true \ No newline at end of file diff --git a/config/src/config.rs b/config/src/config.rs index 646873d1..6a1a2885 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -22,6 +22,7 @@ use dubbo_logger::tracing; use dubbo_utils::yaml_util::yaml_file_parser; use once_cell::sync::OnceCell; use serde::{Deserialize, Serialize}; +use crate::consumer::ConsumerConfig; use super::{protocol::ProtocolConfig, provider::ProviderConfig, service::ServiceConfig}; @@ -44,6 +45,9 @@ pub struct RootConfig { #[serde(default)] pub registries: HashMap, + #[serde(default)] + pub consumer: Option, + #[serde(default)] pub data: HashMap, } @@ -63,6 +67,7 @@ impl RootConfig { protocols: HashMap::new(), registries: HashMap::new(), provider: ProviderConfig::new(), + consumer: None, data: HashMap::new(), } } diff --git a/config/src/consumer.rs b/config/src/consumer.rs new file mode 100644 index 00000000..bdccccd0 --- /dev/null +++ b/config/src/consumer.rs @@ -0,0 +1,41 @@ +use std::collections::HashMap; +use once_cell::sync::OnceCell; +use serde::{Deserialize, Serialize}; +use crate::{get_global_config}; + + +pub static GLOBAL_CONSUMER_CONFIG: OnceCell> = OnceCell::new(); + +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct ConsumerConfig { + pub references: Vec, +} + +impl ConsumerConfig { + pub fn get_global_consumer_config(interface:String) -> Option { + let config=GLOBAL_CONSUMER_CONFIG.get_or_init(|| { + match get_global_config().consumer.clone() { + None => { + HashMap::new() + } + Some(config) => { + let mut consumers=HashMap::new(); + for consumer_config in config.references { + consumers.insert(consumer_config.interface.clone(),consumer_config); + } + consumers + } + } + }); + config.get(interface.as_str()).cloned() + } +} + +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct Consumer { + pub url: String, + pub interface: String, + pub protocol: String, + pub coding: String, + pub compress: bool, +} \ No newline at end of file diff --git a/config/src/lib.rs b/config/src/lib.rs index 0748c667..5804b8f8 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -22,3 +22,4 @@ pub mod protocol; pub mod provider; pub mod registry; pub mod service; +pub mod consumer; diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index 124cfcfd..c8f4075d 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -21,15 +21,22 @@ use futures_util::{future, stream, StreamExt, TryStreamExt}; use aws_smithy_http::body::SdkBody; use http::HeaderValue; +use prost::Message; +use serde::{Deserialize, Serialize}; +use dubbo_config::consumer::{ ConsumerConfig}; use super::builder::ClientBuilder; -use crate::codegen::RpcInvocation; +use crate::codegen::{RpcInvocation, SerdeCodec}; use crate::{ invocation::{IntoStreamingRequest, Metadata, Request, Response}, protocol::BoxInvoker, - triple::{codec::Codec, compression::CompressionEncoding, decode::Decoding, encode::encode}, + triple::{codec::Codec, compression::CompressionEncoding, decode::Decoding}, }; +use crate::invocation::Invocation; +use crate::triple::encode::encode; +use crate::triple::encode_json::encode_json; + #[derive(Debug, Clone, Default)] pub struct TripleClient { @@ -58,6 +65,8 @@ impl TripleClient { uri: http::Uri, path: http::uri::PathAndQuery, body: SdkBody, + is_json: bool, + compression: bool, ) -> http::Request { let mut parts = uri.into_parts(); parts.path_and_query = Some(path); @@ -83,10 +92,18 @@ impl TripleClient { "authority", HeaderValue::from_str(uri.authority().unwrap().as_str()).unwrap(), ); - req.headers_mut().insert( - "content-type", - HeaderValue::from_static("application/grpc+proto"), - ); + if is_json { + req.headers_mut().insert( + "content-type", + HeaderValue::from_static("application/grpc+json"), + ); + } else { + req.headers_mut().insert( + "content-type", + HeaderValue::from_static("application/grpc+proto"), + ); + } + req.headers_mut() .insert("user-agent", HeaderValue::from_static("dubbo-rust/0.1.0")); req.headers_mut() @@ -101,9 +118,11 @@ impl TripleClient { "tri-unit-info", HeaderValue::from_static("dubbo-rust/0.1.0"), ); - if let Some(_encoding) = self.send_compression_encoding { - req.headers_mut() - .insert("grpc-encoding", http::HeaderValue::from_static("gzip")); + if compression { + if let Some(_encoding) = self.send_compression_encoding { + req.headers_mut() + .insert("grpc-encoding", http::HeaderValue::from_static("gzip")); + } } req.headers_mut().insert( "grpc-accept-encoding", @@ -132,186 +151,375 @@ impl TripleClient { path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result, crate::status::Status> - where - C: Codec, - M1: Send + Sync + 'static, - M2: Send + Sync + 'static, + where + C: Codec, + M1: Message + Send + Sync + 'static + Serialize, + M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let req = req.map(|m| stream::once(future::ready(m))); - let body_stream = encode( - codec.encoder(), - req.into_inner().map(Ok), - self.send_compression_encoding, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(body_stream); - let bytes = hyper::body::to_bytes(body).await.unwrap(); - let sdk_body = SdkBody::from(bytes); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), + let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); + let (coding, is_compression) = match config { + None => { (false, true) } + Some(config) => { (config.coding.clone() == "json".to_string(), config.compress) } }; - - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body); - - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), self.send_compression_encoding) - }); - let (mut parts, body) = Response::from_http(resp).into_parts(); - - futures_util::pin_mut!(body); - - let message = body.try_next().await?.ok_or_else(|| { - crate::status::Status::new( - crate::status::Code::Internal, - "Missing response message.".to_string(), - ) - })?; - - if let Some(trailers) = body.trailer().await? { - let mut h = parts.into_headers(); - h.extend(trailers.into_headers()); - parts = Metadata::from_headers(h); + let compression = match is_compression { + true => { self.send_compression_encoding } + false => { None } + }; + if coding { + let mut codec = SerdeCodec::::default(); + let req = req.map(|m| stream::once(future::ready(m))); + let body_stream = encode_json( + codec.encoder(), + req.into_inner().map(Ok), + compression, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(body_stream); + let bytes = hyper::body::to_bytes(body).await.unwrap(); + let sdk_body = SdkBody::from(bytes); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); + + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, codec.decoder(), compression, true) + }); + let (mut parts, body) = Response::from_http(resp).into_parts(); + + futures_util::pin_mut!(body); + + let message = body.try_next().await?.ok_or_else(|| { + crate::status::Status::new( + crate::status::Code::Internal, + "Missing response message.".to_string(), + ) + })?; + + if let Some(trailers) = body.trailer().await? { + let mut h = parts.into_headers(); + h.extend(trailers.into_headers()); + parts = Metadata::from_headers(h); + } + + Ok(Response::from_parts(parts, message)) } - - Ok(Response::from_parts(parts, message)) + Err(err) => Err(err), + } + } else { + let req = req.map(|m| stream::once(future::ready(m))); + let body_stream = encode( + codec.encoder(), + req.into_inner().map(Ok), + compression, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(body_stream); + let bytes = hyper::body::to_bytes(body).await.unwrap(); + let sdk_body = SdkBody::from(bytes); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); + + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, codec.decoder(), compression, false) + }); + let (mut parts, body) = Response::from_http(resp).into_parts(); + + futures_util::pin_mut!(body); + + let message = body.try_next().await?.ok_or_else(|| { + crate::status::Status::new( + crate::status::Code::Internal, + "Missing response message.".to_string(), + ) + })?; + + if let Some(trailers) = body.trailer().await? { + let mut h = parts.into_headers(); + h.extend(trailers.into_headers()); + parts = Metadata::from_headers(h); + } + + Ok(Response::from_parts(parts, message)) + } + Err(err) => Err(err), } - Err(err) => Err(err), } } pub async fn bidi_streaming( &mut self, - req: impl IntoStreamingRequest, + req: impl IntoStreamingRequest, mut codec: C, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result>, crate::status::Status> - where - C: Codec, - M1: Send + Sync + 'static, - M2: Send + Sync + 'static, + where + C: Codec, + M1: Message + Send + Sync + 'static + Serialize, + M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let req = req.into_streaming_request(); - let en = encode( - codec.encoder(), - req.into_inner().map(Ok), - self.send_compression_encoding, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(en); - let sdk_body = SdkBody::from(body); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), + let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); + let (coding, is_compression) = match config { + None => { (false, true) } + Some(config) => { (config.coding.clone() == "json".to_string(), config.compress) } }; - - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body); - - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), self.send_compression_encoding) - }); - - Ok(Response::from_http(resp)) + let compression = match is_compression { + true => { self.send_compression_encoding } + false => { None } + }; + if coding { + let mut codec = SerdeCodec::::default(); + let req = req.into_streaming_request(); + let en = encode_json( + codec.encoder(), + req.into_inner().map(Ok), + compression, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(en); + let sdk_body = SdkBody::from(body); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); + + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, codec.decoder(), compression, true) + }); + + Ok(Response::from_http(resp)) + } + Err(err) => Err(err), + } + } else { + let req = req.into_streaming_request(); + let en = encode( + codec.encoder(), + req.into_inner().map(Ok), + compression, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(en); + let sdk_body = SdkBody::from(body); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); + + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, codec.decoder(), compression, false) + }); + + Ok(Response::from_http(resp)) + } + Err(err) => Err(err), } - Err(err) => Err(err), } } pub async fn client_streaming( &mut self, - req: impl IntoStreamingRequest, + req: impl IntoStreamingRequest, mut codec: C, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result, crate::status::Status> - where - C: Codec, - M1: Send + Sync + 'static, - M2: Send + Sync + 'static, + where + C: Codec, + M1: Message + Send + Sync + 'static + Serialize, + M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let req = req.into_streaming_request(); - let en = encode( - codec.encoder(), - req.into_inner().map(Ok), - self.send_compression_encoding, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(en); - let sdk_body = SdkBody::from(body); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), + let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); + let (coding, is_compression) = match config { + None => { (false, true) } + Some(config) => { (config.coding.clone() == "json".to_string(), config.compress) } }; - - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body); - - // let mut conn = Connection::new().with_host(http_uri); - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), self.send_compression_encoding) - }); - let (mut parts, body) = Response::from_http(resp).into_parts(); - - futures_util::pin_mut!(body); - - let message = body.try_next().await?.ok_or_else(|| { - crate::status::Status::new( - crate::status::Code::Internal, - "Missing response message.".to_string(), - ) - })?; - - if let Some(trailers) = body.trailer().await? { - let mut h = parts.into_headers(); - h.extend(trailers.into_headers()); - parts = Metadata::from_headers(h); + let compression = match is_compression { + true => { self.send_compression_encoding } + false => { None } + }; + if coding { + let mut codec = SerdeCodec::::default(); + let req = req.into_streaming_request(); + let en = encode_json( + codec.encoder(), + req.into_inner().map(Ok), + compression, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(en); + let sdk_body = SdkBody::from(body); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); + + // let mut conn = Connection::new().with_host(http_uri); + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, codec.decoder(), compression, true) + }); + let (mut parts, body) = Response::from_http(resp).into_parts(); + + futures_util::pin_mut!(body); + + let message = body.try_next().await?.ok_or_else(|| { + crate::status::Status::new( + crate::status::Code::Internal, + "Missing response message.".to_string(), + ) + })?; + + if let Some(trailers) = body.trailer().await? { + let mut h = parts.into_headers(); + h.extend(trailers.into_headers()); + parts = Metadata::from_headers(h); + } + + Ok(Response::from_parts(parts, message)) } - - Ok(Response::from_parts(parts, message)) + Err(err) => Err(err), + } + } else { + let req = req.into_streaming_request(); + let en = encode( + codec.encoder(), + req.into_inner().map(Ok), + compression, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(en); + let sdk_body = SdkBody::from(body); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); + + // let mut conn = Connection::new().with_host(http_uri); + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, codec.decoder(), compression, false) + }); + let (mut parts, body) = Response::from_http(resp).into_parts(); + + futures_util::pin_mut!(body); + + let message = body.try_next().await?.ok_or_else(|| { + crate::status::Status::new( + crate::status::Code::Internal, + "Missing response message.".to_string(), + ) + })?; + + if let Some(trailers) = body.trailer().await? { + let mut h = parts.into_headers(); + h.extend(trailers.into_headers()); + parts = Metadata::from_headers(h); + } + + Ok(Response::from_parts(parts, message)) + } + Err(err) => Err(err), } - Err(err) => Err(err), } } @@ -322,47 +530,97 @@ impl TripleClient { path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result>, crate::status::Status> - where - C: Codec, - M1: Send + Sync + 'static, - M2: Send + Sync + 'static, + where + C: Codec, + M1: Message + Send + Sync + 'static + Serialize, + M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let req = req.map(|m| stream::once(future::ready(m))); - let en = encode( - codec.encoder(), - req.into_inner().map(Ok), - self.send_compression_encoding, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(en); - let sdk_body = SdkBody::from(body); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), + let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); + let (coding, is_compression) = match config { + None => { (false, true) } + Some(config) => { (config.coding.clone() == "json".to_string(), config.compress) } }; - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body); - - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), self.send_compression_encoding) - }); - - Ok(Response::from_http(resp)) + let compression = match is_compression { + true => { self.send_compression_encoding } + false => { None } + }; + if coding { + let mut codec = SerdeCodec::::default(); + let req = req.map(|m| stream::once(future::ready(m))); + let en = encode_json( + codec.encoder(), + req.into_inner().map(Ok), + compression, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(en); + let sdk_body = SdkBody::from(body); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); + + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, codec.decoder(), compression, true) + }); + + Ok(Response::from_http(resp)) + } + Err(err) => Err(err), + } + } else { + let req = req.map(|m| stream::once(future::ready(m))); + let en = encode( + codec.encoder(), + req.into_inner().map(Ok), + compression, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(en); + let sdk_body = SdkBody::from(body); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); + + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, codec.decoder(), compression, false) + }); + + Ok(Response::from_http(resp)) + } + Err(err) => Err(err), } - Err(err) => Err(err), } } } diff --git a/dubbo/src/triple/decode.rs b/dubbo/src/triple/decode.rs index 07c1160b..12ff0392 100644 --- a/dubbo/src/triple/decode.rs +++ b/dubbo/src/triple/decode.rs @@ -33,26 +33,28 @@ type BoxBody = http_body::combinators::UnsyncBoxBody { state: State, body: BoxBody, - decoder: Box + Send + 'static>, + decoder: Box + Send + 'static>, buf: BytesMut, trailers: Option, compress: Option, decompress_buf: BytesMut, + is_json: bool, } #[derive(PartialEq)] enum State { ReadHeader, + ReadJSON, ReadBody { len: usize, is_compressed: bool }, Error, } impl Decoding { - pub fn new(body: B, decoder: D, compress: Option) -> Self - where - B: Body + Send + 'static, - B::Error: Into, - D: Decoder + Send + 'static, + pub fn new(body: B, decoder: D, compress: Option, is_json: bool) -> Self + where + B: Body + Send + 'static, + B::Error: Into, + D: Decoder + Send + 'static, { Self { state: State::ReadHeader, @@ -70,6 +72,7 @@ impl Decoding { trailers: None, compress, decompress_buf: BytesMut::new(), + is_json, } } @@ -91,7 +94,48 @@ impl Decoding { trailer.map(|data| data.map(Metadata::from_headers)) } - pub fn decode_chunk(&mut self) -> Result, crate::status::Status> { + pub fn decode_json(&mut self) -> Result, crate::status::Status> { + if self.state == State::ReadHeader { + self.state = State::ReadJSON; + return Ok(None); + } + if let State::ReadJSON = self.state { + if self.buf.is_empty() { + return Ok(None); + } + match self.compress { + None => { self.decompress_buf = self.buf.clone() } + Some(compress) => { + let len = self.buf.len(); + if let Err(err) = decompress( + compress, + &mut self.buf, + &mut self.decompress_buf, + len, + ) { + return Err(crate::status::Status::new( + crate::status::Code::Internal, + err.to_string(), + )); + } + } + } + let len=self.decompress_buf.len(); + let decoding_result = self.decoder.decode(&mut DecodeBuf::new(&mut self.decompress_buf, len)); + + return match decoding_result { + Ok(Some(r)) => { + self.state = State::ReadHeader; + Ok(Some(r)) + } + Ok(None) => Ok(None), + Err(err) => Err(err), + }; + } + Ok(None) + } + + pub fn decode_proto(&mut self) -> Result, crate::status::Status> { if self.state == State::ReadHeader { // buffer is full if self.buf.remaining() < super::consts::HEADER_SIZE { @@ -166,6 +210,14 @@ impl Decoding { Ok(None) } + + pub fn decode_chunk(&mut self) -> Result, crate::status::Status> { + if self.is_json { + self.decode_json() + } else { + self.decode_proto() + } + } } impl Stream for Decoding { @@ -220,3 +272,4 @@ impl Stream for Decoding { (0, None) } } + diff --git a/dubbo/src/triple/decode_json.rs b/dubbo/src/triple/decode_json.rs deleted file mode 100644 index beb07d5d..00000000 --- a/dubbo/src/triple/decode_json.rs +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use std::{pin::Pin, task::Poll}; - -use bytes::{Buf, BufMut, Bytes, BytesMut}; -use futures_util::{ ready, Stream}; -use http_body::Body; -use crate::{ - triple::codec::{DecodeBuf, Decoder}, -}; - -type BoxBody = http_body::combinators::UnsyncBoxBody; - -pub struct DecodingJSON { - state: State, - body: BoxBody, - decoder: Box + Send + 'static>, - buf: BytesMut, - // decompress_buf: BytesMut, -} - -#[derive(PartialEq)] -enum State { - Prepare, - ReadBody, - Ok, - Error, -} - -impl DecodingJSON { - pub fn new(body: B, decoder: D) -> Self - where - B: Body + Send + 'static, - B::Error: Into, - D: Decoder + Send + 'static, - { - Self { - state: State::Prepare, - body: body - .map_data(|mut buf| buf.copy_to_bytes(buf.remaining())) - .map_err(|_err| { - crate::status::Status::new( - crate::status::Code::Internal, - "internal decode err".to_string(), - ) - }) - .boxed_unsync(), - decoder: Box::new(decoder), - buf: BytesMut::with_capacity(super::consts::BUFFER_SIZE), - // decompress_buf: BytesMut::new(), - } - } - - - pub fn decode_chunk(&mut self) -> Result, crate::status::Status> { - if self.state == State::Prepare { - self.state = State::ReadBody; - return Ok(None) - } - - if let State::ReadBody = self.state { - let decoding_result =self.decoder.decode(&mut DecodeBuf::new(&mut self.buf, super::consts::BUFFER_SIZE)); - - return match decoding_result { - Ok(Some(r)) => { - self.state = State::Ok; - Ok(Some(r)) - } - Ok(None) => Ok(None), - Err(err) => Err(err), - }; - } - - Ok(None) - } -} - -impl Stream for DecodingJSON { - type Item = Result; - - fn poll_next( - mut self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll> { - loop { - if self.state == State::Error { - return Poll::Ready(None); - } - - if let Some(item) = self.decode_chunk()? { - return Poll::Ready(Some(Ok(item))); - } - - let chunk = match ready!(Pin::new(&mut self.body).poll_data(cx)) { - Some(Ok(d)) => Some(d), - Some(Err(e)) => { - let _ = std::mem::replace(&mut self.state, State::Error); - let err: crate::Error = e.into(); - return Poll::Ready(Some(Err(crate::status::Status::new( - crate::status::Code::Internal, - err.to_string(), - )))); - } - None => None, - }; - - if let Some(data) = chunk { - self.buf.put(data) - } else { - break; - } - } - - Poll::Ready(None) - } - - fn size_hint(&self) -> (usize, Option) { - (0, None) - } -} diff --git a/dubbo/src/triple/encode.rs b/dubbo/src/triple/encode.rs index b837463b..aaa21490 100644 --- a/dubbo/src/triple/encode.rs +++ b/dubbo/src/triple/encode.rs @@ -32,9 +32,9 @@ pub fn encode( resp_body: B, compression_encoding: Option, ) -> impl TryStream -where - E: Encoder, - B: Stream>, + where + E: Encoder, + B: Stream>, { async_stream::stream! { let mut buf = BytesMut::with_capacity(super::consts::BUFFER_SIZE); @@ -89,9 +89,9 @@ pub fn encode_server( body: B, compression_encoding: Option, ) -> EncodeBody>> -where - E: Encoder, - B: Stream>, + where + E: Encoder, + B: Stream>, { let s = encode(encoder, body, compression_encoding).into_stream(); EncodeBody::new_server(s) @@ -102,9 +102,9 @@ pub fn encode_client( body: B, compression_encoding: Option, ) -> EncodeBody>> -where - E: Encoder, - B: Stream, + where + E: Encoder, + B: Stream, { let s = encode(encoder, body.map(Ok), compression_encoding).into_stream(); EncodeBody::new_client(s) @@ -145,8 +145,8 @@ impl EncodeBody { } impl Body for EncodeBody -where - S: Stream>, + where + S: Stream>, { type Data = Bytes; diff --git a/dubbo/src/triple/encode_json.rs b/dubbo/src/triple/encode_json.rs index 2d2ab507..e6b03162 100644 --- a/dubbo/src/triple/encode_json.rs +++ b/dubbo/src/triple/encode_json.rs @@ -15,17 +15,19 @@ * limitations under the License. */ use crate::status::Status; -use bytes::{ Bytes, BytesMut}; +use bytes::{Bytes, BytesMut}; use futures_core::{Stream, TryStream}; -use futures_util::{ StreamExt, TryStreamExt}; +use futures_util::{StreamExt, TryStreamExt}; use crate::triple::codec::{EncodeBuf, Encoder}; +use crate::triple::compression::{compress, CompressionEncoding}; use crate::triple::encode::EncodeBody; #[allow(unused_must_use)] pub fn encode_json( mut encoder: E, resp_body: B, + compression_encoding: Option, ) -> impl TryStream where E: Encoder, @@ -34,20 +36,25 @@ pub fn encode_json( async_stream::stream! { let mut buf = BytesMut::with_capacity(super::consts::BUFFER_SIZE); futures_util::pin_mut!(resp_body); - + let (enable_compress, mut uncompression_buf) = match compression_encoding { + Some(CompressionEncoding::Gzip) => (true, BytesMut::with_capacity(super::consts::BUFFER_SIZE)), + None => (false, BytesMut::new()) + }; loop { match resp_body.next().await { Some(Ok(item)) => { - match encoder.encode(item, &mut EncodeBuf::new(&mut buf)) { - Ok(_) => { - yield Ok(buf.clone().freeze()); - buf.clear(); - }, - Err(e) => { - yield Err(crate::status::Status::new(crate::status::Code::Internal, format!("encode error: {}", e))); - break; - } - } + if enable_compress { + uncompression_buf.clear(); + encoder.encode(item, &mut EncodeBuf::new(&mut uncompression_buf)) + .map_err(|_e| crate::status::Status::new(crate::status::Code::Internal, "encode error".to_string())); + + let len = uncompression_buf.len(); + compress(compression_encoding.unwrap(), &mut uncompression_buf, &mut buf, len) + .map_err(|_| crate::status::Status::new(crate::status::Code::Internal, "compress error".to_string())); + } else { + encoder.encode(item, &mut EncodeBuf::new(&mut buf)).map_err(|_e| crate::status::Status::new(crate::status::Code::Internal, "encode error".to_string())); + }; + yield Ok(buf.clone().freeze()); }, Some(Err(err)) => yield Err(err.into()), None => break, @@ -59,12 +66,12 @@ pub fn encode_json( pub fn encode_server_json( encoder: E, body: B, + compress: Option, ) -> EncodeBody>> where E: Encoder, B: Stream>, { - let s = encode_json(encoder, body).into_stream(); + let s = encode_json(encoder, body, compress).into_stream(); EncodeBody::new_server(s) -} - +} \ No newline at end of file diff --git a/dubbo/src/triple/mod.rs b/dubbo/src/triple/mod.rs index a2c85ed1..9cc51bc9 100644 --- a/dubbo/src/triple/mod.rs +++ b/dubbo/src/triple/mod.rs @@ -23,5 +23,4 @@ pub mod decode; pub mod encode; pub mod server; pub mod transport; -mod decode_json; mod encode_json; diff --git a/dubbo/src/triple/server/triple.rs b/dubbo/src/triple/server/triple.rs index a6d389f5..afe07666 100644 --- a/dubbo/src/triple/server/triple.rs +++ b/dubbo/src/triple/server/triple.rs @@ -15,7 +15,9 @@ * limitations under the License. */ +use std::marker::PhantomData; use futures_util::{future, stream, StreamExt, TryStreamExt}; +use http::HeaderValue; use http_body::Body; use prost::Message; use serde::{Deserialize, Serialize}; @@ -33,7 +35,6 @@ use crate::{ }; use dubbo_config::BusinessConfig; use crate::codegen::{ProstCodec, SerdeCodec}; -use crate::triple::decode_json::DecodingJSON; use crate::triple::encode_json::encode_server_json; pub const GRPC_ACCEPT_ENCODING: &str = "grpc-accept-encoding"; @@ -41,17 +42,15 @@ pub const GRPC_ENCODING: &str = "grpc-encoding"; pub struct TripleServer { - prost_codec: ProstCodec, - serde_codec: SerdeCodec, + _pd: PhantomData<(T, V)>, compression: Option, } impl TripleServer { pub fn new() -> Self { Self { - prost_codec: ProstCodec::default(), - serde_codec: SerdeCodec::default(), - compression: None, + _pd: PhantomData, + compression: Some(CompressionEncoding::Gzip), } } } @@ -71,43 +70,86 @@ impl TripleServer B: Body + Send + 'static, B::Error: Into + Send, { - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; - } + let is_json = req.headers().get("content-type").unwrap() == "application/grpc+json"; + if is_json { + let mut codec = SerdeCodec::::default(); + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } - // Get grpc_encoding from http_header, decompress message. - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; + // Get grpc_encoding from http_header, decompress message. + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; - let req_stream = req.map(|body| Decoding::new(body, self.prost_codec.decoder(), compression)); + let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, true)); - let resp = service.call(Request::from_http(req_stream)).await; + let resp = service.call(Request::from_http(req_stream)).await; - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + + let resp_body = encode_server_json( + codec.encoder(), + stream::once(future::ready(resp_body)).map(Ok).into_stream(), + accept_encoding, + ); + + parts.headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/grpc+json"), + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); + } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) + } else { + let mut codec = ProstCodec::::default(); + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } + + // Get grpc_encoding from http_header, decompress message. + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; + + let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, false)); + + let resp = service.call(Request::from_http(req_stream)).await; + + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + + let resp_body = encode_server( + codec.encoder(), + stream::once(future::ready(resp_body)).map(Ok).into_stream(), + accept_encoding, + ); - let resp_body = encode_server( - self.prost_codec.encoder(), - stream::once(future::ready(resp_body)).map(Ok).into_stream(), - accept_encoding, - ); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); + parts.headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/grpc+proto"), + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); + } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) } pub async fn bidi_streaming( @@ -121,40 +163,80 @@ impl TripleServer B: Body + Send + 'static, B::Error: Into + Send, { - // Firstly, get grpc_accept_encoding from http_header, get compression - // Secondly, if server enable compression and compression is valid, this method should compress response - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; - } + let is_json = req.headers().get("content-type").unwrap() == "application/grpc+json"; + if is_json { + let mut codec = SerdeCodec::::default(); + // Firstly, get grpc_accept_encoding from http_header, get compression + // Secondly, if server enable compression and compression is valid, this method should compress response + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } - // Get grpc_encoding from http_header, decompress message. - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; + // Get grpc_encoding from http_header, decompress message. + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; - let req_stream = req.map(|body| Decoding::new(body, self.prost_codec.decoder(), compression)); + let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, is_json)); - let resp = service.call(Request::from_http(req_stream)).await; + let resp = service.call(Request::from_http(req_stream)).await; - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - let resp_body = encode_server(self.prost_codec.encoder(), resp_body, compression); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + let resp_body = encode_server_json(codec.encoder(), resp_body, compression); + + parts.headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/grpc+json"), + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); + } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) + } else { + let mut codec = ProstCodec::::default(); + // Firstly, get grpc_accept_encoding from http_header, get compression + // Secondly, if server enable compression and compression is valid, this method should compress response + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } + + // Get grpc_encoding from http_header, decompress message. + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; + + let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, false)); + + let resp = service.call(Request::from_http(req_stream)).await; + + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + let resp_body = encode_server(codec.encoder(), resp_body, compression); + + parts.headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/grpc+proto"), + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); + } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) } pub async fn server_streaming( @@ -168,48 +250,94 @@ impl TripleServer B: Body + Send + 'static, B::Error: Into + Send, { - // Firstly, get grpc_accept_encoding from http_header, get compression - // Secondly, if server enable compression and compression is valid, this method should compress response - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; - } + let is_json = req.headers().get("content-type").unwrap() == "application/grpc+json"; + if is_json { + let mut codec = SerdeCodec::::default(); + // Firstly, get grpc_accept_encoding from http_header, get compression + // Secondly, if server enable compression and compression is valid, this method should compress response + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } - // Get grpc_encoding from http_header, decompress message. - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; + // Get grpc_encoding from http_header, decompress message. + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; + let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, true)); + let (parts, mut body) = Request::from_http(req_stream).into_parts(); + let msg = body.try_next().await.unwrap().ok_or_else(|| { + crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) + }); + let msg = match msg { + Ok(v) => v, + Err(err) => return err.to_http(), + }; - let req_stream = req.map(|body| Decoding::new(body, self.prost_codec.decoder(), compression)); - let (parts, mut body) = Request::from_http(req_stream).into_parts(); - let msg = body.try_next().await.unwrap().ok_or_else(|| { - crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) - }); - let msg = match msg { - Ok(v) => v, - Err(err) => return err.to_http(), - }; + let resp = service.call(Request::from_parts(parts, msg)).await; - let resp = service.call(Request::from_parts(parts, msg)).await; + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + let resp_body = encode_server_json(codec.encoder(), resp_body, compression); - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - let resp_body = encode_server(self.prost_codec.encoder(), resp_body, compression); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); + parts.headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/grpc+json"), + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); + } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) + } else { + let mut codec = ProstCodec::::default(); + // Firstly, get grpc_accept_encoding from http_header, get compression + // Secondly, if server enable compression and compression is valid, this method should compress response + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } + + // Get grpc_encoding from http_header, decompress message. + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; + let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, false)); + let (parts, mut body) = Request::from_http(req_stream).into_parts(); + let msg = body.try_next().await.unwrap().ok_or_else(|| { + crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) + }); + let msg = match msg { + Ok(v) => v, + Err(err) => return err.to_http(), + }; + + let resp = service.call(Request::from_parts(parts, msg)).await; + + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + let resp_body = encode_server(codec.encoder(), resp_body, compression); + + parts.headers.insert( + http::header::CONTENT_TYPE, + http::HeaderValue::from_static("application/grpc+proto"), + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); + } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) } pub async fn unary( @@ -222,8 +350,20 @@ impl TripleServer B: Body + Send + 'static, B::Error: Into + Send, { - if req.headers().get("content-type").unwrap() == "application/json" { - let req_stream = req.map(|body| DecodingJSON::new(body, self.serde_codec.decoder())); + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } + + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; + let content_type = req.headers().get("content-type").cloned().unwrap_or(HeaderValue::from_str("application/json").unwrap()); + let is_json = content_type == "application/json" || content_type == "application/grpc+json"; + if is_json { + let mut codec = SerdeCodec::::default(); + let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, is_json)); let (parts, mut body) = Request::from_http(req_stream).into_parts(); let msg = body.try_next().await.unwrap().ok_or_else(|| { crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) @@ -232,33 +372,33 @@ impl TripleServer Ok(v) => v, Err(err) => return err.to_http(), }; + let resp = service.call(Request::from_parts(parts, msg)).await; + let (mut parts, resp_body) = match resp { Ok(v) => v.into_http().into_parts(), Err(err) => return err.to_http(), }; - let resp_body = encode_server_json( - self.serde_codec.encoder(), + codec.encoder(), stream::once(future::ready(resp_body)).map(Ok).into_stream(), + accept_encoding, ); + parts.headers.insert( http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/json"), + content_type, ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); + } parts.status = http::StatusCode::OK; http::Response::from_parts(parts, BoxBody::new(resp_body)) - } else { - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; - } - - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; - let req_stream = req.map(|body| Decoding::new(body, self.prost_codec.decoder(), compression)); + }else { + let mut codec = ProstCodec::::default(); + let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, is_json)); let (parts, mut body) = Request::from_http(req_stream).into_parts(); let msg = body.try_next().await.unwrap().ok_or_else(|| { crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) @@ -275,14 +415,14 @@ impl TripleServer Err(err) => return err.to_http(), }; let resp_body = encode_server( - self.prost_codec.encoder(), + codec.encoder(), stream::once(future::ready(resp_body)).map(Ok).into_stream(), accept_encoding, ); parts.headers.insert( http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc"), + http::HeaderValue::from_static("application/grpc+proto"), ); if let Some(encoding) = accept_encoding { parts diff --git a/examples/echo/src/echo/client.rs b/examples/echo/src/echo/client.rs index 0a2f150b..2fc4d6f0 100644 --- a/examples/echo/src/echo/client.rs +++ b/examples/echo/src/echo/client.rs @@ -16,8 +16,11 @@ */ use dubbo::codegen::*; -use example_echo::generated::generated::{echo_client::EchoClient, EchoRequest}; +use example_echo::generated::generated::{echo_client::EchoClient, EchoRequest, EchoResponse}; use futures_util::StreamExt; +use prost::bytes::BytesMut; +use dubbo::triple::codec::{Decoder, EncodeBuf, Encoder}; +use dubbo::triple::consts::BUFFER_SIZE; pub struct FakeFilter {} @@ -28,6 +31,18 @@ impl Filter for FakeFilter { } } +#[test] +fn test_x(){ + let message=EchoRequest{ + message: "hello!".to_string(), + }; + let mut codec =SerdeCodec::::default(); + let mut byte_buf=BytesMut::with_capacity(BUFFER_SIZE); + let mut buf =EncodeBuf::new(&mut byte_buf); + let _res=codec.encoder().encode(message, &mut buf); + println!("{:?}", buf); +} + #[tokio::main] async fn main() { dubbo_logger::init(); @@ -71,7 +86,7 @@ async fn main() { }; let (_parts, resp_body) = client_streaming_resp.into_parts(); println!("client streaming, Response: {:?}", resp_body); - + // let data = vec![ EchoRequest { message: "msg1 from client".to_string(), diff --git a/examples/echo/src/example.http b/examples/echo/src/example.http index 8a54d96e..4cba3332 100644 --- a/examples/echo/src/example.http +++ b/examples/echo/src/example.http @@ -4,4 +4,4 @@ Content-Type: application/json { "message":"1" -} +} \ No newline at end of file diff --git a/examples/greeter/src/example.http b/examples/greeter/src/example.http index e7255cfd..c7368068 100644 --- a/examples/greeter/src/example.http +++ b/examples/greeter/src/example.http @@ -3,6 +3,6 @@ Host: 127.0.0.1:8888 Content-Type: application/json { - "message":"hello,你好" + "name":"hello!This is a test for unary" } diff --git a/examples/greeter/src/greeter/server.rs b/examples/greeter/src/greeter/server.rs index 94e4e53b..f143e25b 100644 --- a/examples/greeter/src/greeter/server.rs +++ b/examples/greeter/src/greeter/server.rs @@ -76,7 +76,7 @@ impl Greeter for GreeterServerImpl { request: Request, ) -> Result, dubbo::status::Status> { info!("GreeterServer::greet {:?}", request.metadata); - + println!("{:?}", request.into_inner()); Ok(Response::new(GreeterReply { message: "hello, dubbo-rust".to_string(), })) From 52dbcd6975aba3717da043c5795f5932cccbeb18 Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Sun, 13 Aug 2023 22:27:38 -0400 Subject: [PATCH 05/11] fix: Fixed a bug related to compression(#145) --- application.yaml | 7 ++++++- dubbo/src/triple/client/triple.rs | 8 ++++---- examples/echo/src/echo/client.rs | 16 +--------------- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/application.yaml b/application.yaml index 964484a2..6fb48c0e 100644 --- a/application.yaml +++ b/application.yaml @@ -22,5 +22,10 @@ dubbo: - url: tri://localhost:20000 interface: org.apache.dubbo.sample.tri.Greeter protocol: tri - coding: json + coding: proto + compress: false + - url: tri://localhost:20000 + interface: grpc.examples.echo.Echo + protocol: tri + coding: proto compress: true \ No newline at end of file diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index c8f4075d..41e35680 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -122,12 +122,12 @@ impl TripleClient { if let Some(_encoding) = self.send_compression_encoding { req.headers_mut() .insert("grpc-encoding", http::HeaderValue::from_static("gzip")); + req.headers_mut().insert( + "grpc-accept-encoding", + http::HeaderValue::from_static("gzip"), + ); } } - req.headers_mut().insert( - "grpc-accept-encoding", - http::HeaderValue::from_static("gzip"), - ); // const ( // TripleContentType = "application/grpc+proto" diff --git a/examples/echo/src/echo/client.rs b/examples/echo/src/echo/client.rs index 2fc4d6f0..206796c1 100644 --- a/examples/echo/src/echo/client.rs +++ b/examples/echo/src/echo/client.rs @@ -16,11 +16,8 @@ */ use dubbo::codegen::*; -use example_echo::generated::generated::{echo_client::EchoClient, EchoRequest, EchoResponse}; +use example_echo::generated::generated::{echo_client::EchoClient, EchoRequest}; use futures_util::StreamExt; -use prost::bytes::BytesMut; -use dubbo::triple::codec::{Decoder, EncodeBuf, Encoder}; -use dubbo::triple::consts::BUFFER_SIZE; pub struct FakeFilter {} @@ -31,17 +28,6 @@ impl Filter for FakeFilter { } } -#[test] -fn test_x(){ - let message=EchoRequest{ - message: "hello!".to_string(), - }; - let mut codec =SerdeCodec::::default(); - let mut byte_buf=BytesMut::with_capacity(BUFFER_SIZE); - let mut buf =EncodeBuf::new(&mut byte_buf); - let _res=codec.encoder().encode(message, &mut buf); - println!("{:?}", buf); -} #[tokio::main] async fn main() { From 17c41eefddc562a2559999b181af9e0390b3e844 Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Wed, 16 Aug 2023 03:58:03 -0400 Subject: [PATCH 06/11] perf: Improved code reuse-related logic(#145) Optimized the logic of TripleServer and TripleClient, achieving code reuse. Merged encoding and encoding_json --- application.yaml | 4 +- config/src/consumer.rs | 2 +- dubbo-build/src/client.rs | 16 +- dubbo/src/codegen.rs | 2 +- dubbo/src/triple/client/triple.rs | 635 +++++++----------- dubbo/src/triple/codec/mod.rs | 32 +- dubbo/src/triple/codec/serde_codec.rs | 1 + dubbo/src/triple/decode.rs | 5 +- dubbo/src/triple/encode.rs | 57 +- dubbo/src/triple/encode_json.rs | 77 --- dubbo/src/triple/mod.rs | 1 - dubbo/src/triple/server/triple.rs | 478 +++++-------- .../echo/src/generated/grpc.examples.echo.rs | 8 +- 13 files changed, 496 insertions(+), 822 deletions(-) delete mode 100644 dubbo/src/triple/encode_json.rs diff --git a/application.yaml b/application.yaml index 6fb48c0e..9add3256 100644 --- a/application.yaml +++ b/application.yaml @@ -22,10 +22,10 @@ dubbo: - url: tri://localhost:20000 interface: org.apache.dubbo.sample.tri.Greeter protocol: tri - coding: proto + codec: proto compress: false - url: tri://localhost:20000 interface: grpc.examples.echo.Echo protocol: tri - coding: proto + codec: json compress: true \ No newline at end of file diff --git a/config/src/consumer.rs b/config/src/consumer.rs index bdccccd0..d5ca220e 100644 --- a/config/src/consumer.rs +++ b/config/src/consumer.rs @@ -36,6 +36,6 @@ pub struct Consumer { pub url: String, pub interface: String, pub protocol: String, - pub coding: String, + pub codec: String, pub compress: bool, } \ No newline at end of file diff --git a/dubbo-build/src/client.rs b/dubbo-build/src/client.rs index bfcfe45b..a3c2df2e 100644 --- a/dubbo-build/src/client.rs +++ b/dubbo-build/src/client.rs @@ -20,7 +20,6 @@ use crate::{Method, Service}; use proc_macro2::TokenStream; use quote::{format_ident, quote}; -pub const CODEC_PATH: &str = "dubbo::codegen::ProstCodec"; /// Generate service for client. /// @@ -167,7 +166,6 @@ fn generate_unary( compile_well_known_types: bool, path: String, ) -> TokenStream { - let codec_name = syn::parse_str::(CODEC_PATH).unwrap(); let ident = format_ident!("{}", method.name()); let (request, response) = method.request_response_name(proto_path, compile_well_known_types); let method_name = method.identifier(); @@ -177,7 +175,7 @@ fn generate_unary( &mut self, request: Request<#request>, ) -> Result, dubbo::status::Status> { - let codec = #codec_name::<#request, #response>::default(); + let codec = dubbo::codegen::FakeCodec::<#request, #response>::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from(#service_unique_name)) .with_method_name(String::from(#method_name)); @@ -199,9 +197,7 @@ fn generate_server_streaming( compile_well_known_types: bool, path: String, ) -> TokenStream { - let codec_name = syn::parse_str::(CODEC_PATH).unwrap(); let ident = format_ident!("{}", method.name()); - let (request, response) = method.request_response_name(proto_path, compile_well_known_types); let method_name = method.identifier(); @@ -211,7 +207,7 @@ fn generate_server_streaming( request: Request<#request>, ) -> Result>, dubbo::status::Status> { - let codec = #codec_name::<#request, #response>::default(); + let codec = dubbo::codegen::FakeCodec::<#request, #response>::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from(#service_unique_name)) .with_method_name(String::from(#method_name)); @@ -233,9 +229,7 @@ fn generate_client_streaming( compile_well_known_types: bool, path: String, ) -> TokenStream { - let codec_name = syn::parse_str::(CODEC_PATH).unwrap(); let ident = format_ident!("{}", method.name()); - let (request, response) = method.request_response_name(proto_path, compile_well_known_types); let method_name = method.identifier(); @@ -244,7 +238,7 @@ fn generate_client_streaming( &mut self, request: impl IntoStreamingRequest ) -> Result, dubbo::status::Status> { - let codec = #codec_name::<#request, #response>::default(); + let codec = dubbo::codegen::FakeCodec::<#request, #response>::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from(#service_unique_name)) .with_method_name(String::from(#method_name)); @@ -266,9 +260,7 @@ fn generate_streaming( compile_well_known_types: bool, path: String, ) -> TokenStream { - let codec_name = syn::parse_str::(CODEC_PATH).unwrap(); let ident = format_ident!("{}", method.name()); - let (request, response) = method.request_response_name(proto_path, compile_well_known_types); let method_name = method.identifier(); @@ -277,7 +269,7 @@ fn generate_streaming( &mut self, request: impl IntoStreamingRequest ) -> Result>, dubbo::status::Status> { - let codec = #codec_name::<#request, #response>::default(); + let codec = dubbo::codegen::FakeCodec::<#request, #response>::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from(#service_unique_name)) .with_method_name(String::from(#method_name)); diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index aaabb438..3bf54da7 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -34,7 +34,7 @@ pub use super::{ registry::{BoxRegistry, Registry}, triple::{ client::TripleClient, - codec::{prost::ProstCodec, serde_codec::SerdeCodec,Codec}, + codec::{prost::ProstCodec, serde_codec::SerdeCodec,Codec,FakeCodec}, decode::Decoding, server::{ service::{ClientStreamingSvc, ServerStreamingSvc, StreamingSvc, UnarySvc}, diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index 41e35680..5a9e5d0c 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -23,10 +23,10 @@ use aws_smithy_http::body::SdkBody; use http::HeaderValue; use prost::Message; use serde::{Deserialize, Serialize}; -use dubbo_config::consumer::{ ConsumerConfig}; +use dubbo_config::consumer::{ConsumerConfig}; use super::builder::ClientBuilder; -use crate::codegen::{RpcInvocation, SerdeCodec}; +use crate::codegen::{FakeCodec, ProstCodec, RpcInvocation, SerdeCodec}; use crate::{ invocation::{IntoStreamingRequest, Metadata, Request, Response}, @@ -34,8 +34,9 @@ use crate::{ triple::{codec::Codec, compression::CompressionEncoding, decode::Decoding}, }; use crate::invocation::Invocation; +use crate::status::Status; +use crate::triple::codec::{Decoder, Encoder}; use crate::triple::encode::encode; -use crate::triple::encode_json::encode_json; #[derive(Debug, Clone, Default)] @@ -144,483 +145,323 @@ impl TripleClient { req } - pub async fn unary( + pub async fn unary( &mut self, req: Request, - mut codec: C, + _codec: FakeCodec, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result, crate::status::Status> where - C: Codec, M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); - let (coding, is_compression) = match config { + let (is_json, is_compression) = match config { None => { (false, true) } - Some(config) => { (config.coding.clone() == "json".to_string(), config.compress) } + Some(config) => { (config.codec.clone() == "json".to_string(), config.compress) } }; let compression = match is_compression { true => { self.send_compression_encoding } false => { None } }; - if coding { - let mut codec = SerdeCodec::::default(); - let req = req.map(|m| stream::once(future::ready(m))); - let body_stream = encode_json( - codec.encoder(), - req.into_inner().map(Ok), - compression, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(body_stream); - let bytes = hyper::body::to_bytes(body).await.unwrap(); - let sdk_body = SdkBody::from(bytes); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; - - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); - - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), compression, true) - }); - let (mut parts, body) = Response::from_http(resp).into_parts(); - - futures_util::pin_mut!(body); - - let message = body.try_next().await?.ok_or_else(|| { - crate::status::Status::new( - crate::status::Code::Internal, - "Missing response message.".to_string(), - ) - })?; - - if let Some(trailers) = body.trailer().await? { - let mut h = parts.into_headers(); - h.extend(trailers.into_headers()); - parts = Metadata::from_headers(h); - } - - Ok(Response::from_parts(parts, message)) - } - Err(err) => Err(err), + let (decoder, encoder): (Box + Send + 'static>, Box + Send + 'static>) = match is_json { + true => { + let mut codec = SerdeCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } - } else { - let req = req.map(|m| stream::once(future::ready(m))); - let body_stream = encode( - codec.encoder(), - req.into_inner().map(Ok), - compression, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(body_stream); - let bytes = hyper::body::to_bytes(body).await.unwrap(); - let sdk_body = SdkBody::from(bytes); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; - - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); - - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), compression, false) - }); - let (mut parts, body) = Response::from_http(resp).into_parts(); - - futures_util::pin_mut!(body); - - let message = body.try_next().await?.ok_or_else(|| { - crate::status::Status::new( - crate::status::Code::Internal, - "Missing response message.".to_string(), - ) - })?; - - if let Some(trailers) = body.trailer().await? { - let mut h = parts.into_headers(); - h.extend(trailers.into_headers()); - parts = Metadata::from_headers(h); - } - - Ok(Response::from_parts(parts, message)) + false => { + let mut codec = ProstCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) + } + }; + let req = req.map(|m| stream::once(future::ready(m))); + let body_stream = encode( + encoder, + req.into_inner().map(Ok), + compression, + is_json, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(body_stream); + let bytes = hyper::body::to_bytes(body).await.unwrap(); + let sdk_body = SdkBody::from(bytes); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, is_json, is_compression); + + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, decoder, compression, is_json) + }); + let (mut parts, body) = Response::from_http(resp).into_parts(); + + futures_util::pin_mut!(body); + + let message = body.try_next().await?.ok_or_else(|| { + crate::status::Status::new( + crate::status::Code::Internal, + "Missing response message.".to_string(), + ) + })?; + + if let Some(trailers) = body.trailer().await? { + let mut h = parts.into_headers(); + h.extend(trailers.into_headers()); + parts = Metadata::from_headers(h); } - Err(err) => Err(err), + + Ok(Response::from_parts(parts, message)) } + Err(err) => Err(err), } } - pub async fn bidi_streaming( + + pub async fn bidi_streaming( &mut self, req: impl IntoStreamingRequest, - mut codec: C, + _codec: FakeCodec, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result>, crate::status::Status> where - C: Codec, M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); - let (coding, is_compression) = match config { + let (is_json, is_compression) = match config { None => { (false, true) } - Some(config) => { (config.coding.clone() == "json".to_string(), config.compress) } + Some(config) => { (config.codec.clone() == "json".to_string(), config.compress) } }; let compression = match is_compression { true => { self.send_compression_encoding } false => { None } }; - if coding { - let mut codec = SerdeCodec::::default(); - let req = req.into_streaming_request(); - let en = encode_json( - codec.encoder(), - req.into_inner().map(Ok), - compression, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(en); - let sdk_body = SdkBody::from(body); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; - - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); - - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), compression, true) - }); - - Ok(Response::from_http(resp)) - } - Err(err) => Err(err), + let (decoder, encoder): (Box + Send + 'static>, Box + Send + 'static>) = match is_json { + true => { + let mut codec = SerdeCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } - } else { - let req = req.into_streaming_request(); - let en = encode( - codec.encoder(), - req.into_inner().map(Ok), - compression, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(en); - let sdk_body = SdkBody::from(body); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; - - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); - - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), compression, false) - }); - - Ok(Response::from_http(resp)) - } - Err(err) => Err(err), + false => { + let mut codec = ProstCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } + }; + let req = req.into_streaming_request(); + let en = encode( + encoder, + req.into_inner().map(Ok), + compression, + is_json, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(en); + let sdk_body = SdkBody::from(body); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, is_json, is_compression); + + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, decoder, compression, is_json) + }); + + Ok(Response::from_http(resp)) + } + Err(err) => Err(err), } } - pub async fn client_streaming( + pub async fn client_streaming( &mut self, req: impl IntoStreamingRequest, - mut codec: C, + _codec: FakeCodec, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result, crate::status::Status> where - C: Codec, M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); - let (coding, is_compression) = match config { + let (is_json, is_compression) = match config { None => { (false, true) } - Some(config) => { (config.coding.clone() == "json".to_string(), config.compress) } + Some(config) => { (config.codec.clone() == "json".to_string(), config.compress) } }; let compression = match is_compression { true => { self.send_compression_encoding } false => { None } }; - if coding { - let mut codec = SerdeCodec::::default(); - let req = req.into_streaming_request(); - let en = encode_json( - codec.encoder(), - req.into_inner().map(Ok), - compression, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(en); - let sdk_body = SdkBody::from(body); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; - - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); - - // let mut conn = Connection::new().with_host(http_uri); - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), compression, true) - }); - let (mut parts, body) = Response::from_http(resp).into_parts(); - - futures_util::pin_mut!(body); - - let message = body.try_next().await?.ok_or_else(|| { - crate::status::Status::new( - crate::status::Code::Internal, - "Missing response message.".to_string(), - ) - })?; - - if let Some(trailers) = body.trailer().await? { - let mut h = parts.into_headers(); - h.extend(trailers.into_headers()); - parts = Metadata::from_headers(h); - } - - Ok(Response::from_parts(parts, message)) - } - Err(err) => Err(err), + let (decoder, encoder): (Box + Send + 'static>, Box + Send + 'static>) = match is_json { + true => { + let mut codec = SerdeCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } - } else { - let req = req.into_streaming_request(); - let en = encode( - codec.encoder(), - req.into_inner().map(Ok), - compression, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(en); - let sdk_body = SdkBody::from(body); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; - - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); - - // let mut conn = Connection::new().with_host(http_uri); - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), compression, false) - }); - let (mut parts, body) = Response::from_http(resp).into_parts(); - - futures_util::pin_mut!(body); - - let message = body.try_next().await?.ok_or_else(|| { - crate::status::Status::new( - crate::status::Code::Internal, - "Missing response message.".to_string(), - ) - })?; - - if let Some(trailers) = body.trailer().await? { - let mut h = parts.into_headers(); - h.extend(trailers.into_headers()); - parts = Metadata::from_headers(h); - } - - Ok(Response::from_parts(parts, message)) + false => { + let mut codec = ProstCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) + } + }; + let req = req.into_streaming_request(); + let en = encode( + encoder, + req.into_inner().map(Ok), + compression, + is_json, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(en); + let sdk_body = SdkBody::from(body); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, is_json, is_compression); + + // let mut conn = Connection::new().with_host(http_uri); + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, decoder, compression, is_json) + }); + let (mut parts, body) = Response::from_http(resp).into_parts(); + + futures_util::pin_mut!(body); + + let message = body.try_next().await?.ok_or_else(|| { + crate::status::Status::new( + crate::status::Code::Internal, + "Missing response message.".to_string(), + ) + })?; + + if let Some(trailers) = body.trailer().await? { + let mut h = parts.into_headers(); + h.extend(trailers.into_headers()); + parts = Metadata::from_headers(h); } - Err(err) => Err(err), + + Ok(Response::from_parts(parts, message)) } + Err(err) => Err(err), } } - pub async fn server_streaming( + pub async fn server_streaming( &mut self, req: Request, - mut codec: C, + _codec: FakeCodec, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result>, crate::status::Status> where - C: Codec, M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); - let (coding, is_compression) = match config { + let (is_json, is_compression) = match config { None => { (false, true) } - Some(config) => { (config.coding.clone() == "json".to_string(), config.compress) } + Some(config) => { (config.codec.clone() == "json".to_string(), config.compress) } }; let compression = match is_compression { true => { self.send_compression_encoding } false => { None } }; - if coding { - let mut codec = SerdeCodec::::default(); - let req = req.map(|m| stream::once(future::ready(m))); - let en = encode_json( - codec.encoder(), - req.into_inner().map(Ok), - compression, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(en); - let sdk_body = SdkBody::from(body); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); - - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), compression, true) - }); - - Ok(Response::from_http(resp)) - } - Err(err) => Err(err), + + let (decoder, encoder): (Box + Send + 'static>, Box + Send + 'static>) = match is_json { + true => { + let mut codec = SerdeCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } - } else { - let req = req.map(|m| stream::once(future::ready(m))); - let en = encode( - codec.encoder(), - req.into_inner().map(Ok), - compression, - ) - .into_stream(); - let body = hyper::Body::wrap_stream(en); - let sdk_body = SdkBody::from(body); - - let mut conn = match self.invoker.clone() { - Some(v) => v, - None => self - .builder - .clone() - .unwrap() - .build(invocation.into()) - .unwrap(), - }; - let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, coding, is_compression); - - let response = conn - .call(req) - .await - .map_err(|err| crate::status::Status::from_error(err.into())); - - match response { - Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, codec.decoder(), compression, false) - }); - - Ok(Response::from_http(resp)) - } - Err(err) => Err(err), + false => { + let mut codec = ProstCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) + } + }; + let req = req.map(|m| stream::once(future::ready(m))); + let en = encode( + encoder, + req.into_inner().map(Ok), + compression, + is_json, + ) + .into_stream(); + let body = hyper::Body::wrap_stream(en); + let sdk_body = SdkBody::from(body); + + let mut conn = match self.invoker.clone() { + Some(v) => v, + None => self + .builder + .clone() + .unwrap() + .build(invocation.into()) + .unwrap(), + }; + let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); + let req = self.map_request(http_uri.clone(), path, sdk_body, is_json, is_compression); + + let response = conn + .call(req) + .await + .map_err(|err| crate::status::Status::from_error(err.into())); + + match response { + Ok(v) => { + let resp = v.map(|body| { + Decoding::new(body, decoder, compression, is_json) + }); + + Ok(Response::from_http(resp)) } + Err(err) => Err(err), } } } diff --git a/dubbo/src/triple/codec/mod.rs b/dubbo/src/triple/codec/mod.rs index 2ba79865..a219d8c0 100644 --- a/dubbo/src/triple/codec/mod.rs +++ b/dubbo/src/triple/codec/mod.rs @@ -20,6 +20,9 @@ pub mod prost; pub mod serde_codec; use std::io; +use std::marker::PhantomData; +use ::prost::Message; +use serde::{Deserialize, Serialize}; pub use self::buffer::{DecodeBuf, EncodeBuf}; use crate::status::Status; @@ -31,9 +34,9 @@ pub trait Codec { type Decode: Send + 'static; /// The encoder that can encode a message. - type Encoder: Encoder + Send + 'static; + type Encoder: Encoder + Send + 'static; /// The encoder that can decode a message. - type Decoder: Decoder + Send + 'static; + type Decoder: Decoder + Send + 'static; /// Fetch the encoder. fn encoder(&mut self) -> Self::Encoder; @@ -70,3 +73,28 @@ pub trait Decoder { /// for you. fn decode(&mut self, src: &mut DecodeBuf<'_>) -> Result, Self::Error>; } + +trait FakeTypes { + type Encode: Send + 'static; + type Decode: Send + 'static; +} + +#[derive(Debug)] +pub struct FakeCodec { + _pd: PhantomData<(T, U)>, +} + +impl Default for FakeCodec { + fn default() -> Self { + Self { _pd: PhantomData } + } +} + +impl<'a, T, U> FakeTypes for FakeCodec + where + T: Message + Serialize + Send + 'static, + U: Message + Deserialize<'a> + Send + 'static, +{ + type Encode = T; + type Decode = U; +} \ No newline at end of file diff --git a/dubbo/src/triple/codec/serde_codec.rs b/dubbo/src/triple/codec/serde_codec.rs index 308a939a..60a75076 100644 --- a/dubbo/src/triple/codec/serde_codec.rs +++ b/dubbo/src/triple/codec/serde_codec.rs @@ -87,3 +87,4 @@ impl<'a, U: Deserialize<'a>> Decoder for SerdeDecoder { Ok(Some(U::deserialize(&mut de).unwrap())) } } + diff --git a/dubbo/src/triple/decode.rs b/dubbo/src/triple/decode.rs index 12ff0392..47398132 100644 --- a/dubbo/src/triple/decode.rs +++ b/dubbo/src/triple/decode.rs @@ -50,11 +50,10 @@ enum State { } impl Decoding { - pub fn new(body: B, decoder: D, compress: Option, is_json: bool) -> Self + pub fn new(body: B, decoder: Box + Send + 'static>, compress: Option, is_json: bool) -> Self where B: Body + Send + 'static, B::Error: Into, - D: Decoder + Send + 'static, { Self { state: State::ReadHeader, @@ -67,7 +66,7 @@ impl Decoding { ) }) .boxed_unsync(), - decoder: Box::new(decoder), + decoder, buf: BytesMut::with_capacity(super::consts::BUFFER_SIZE), trailers: None, compress, diff --git a/dubbo/src/triple/encode.rs b/dubbo/src/triple/encode.rs index aaa21490..e06e42ae 100644 --- a/dubbo/src/triple/encode.rs +++ b/dubbo/src/triple/encode.rs @@ -28,13 +28,13 @@ use crate::triple::codec::{EncodeBuf, Encoder}; #[allow(unused_must_use)] pub fn encode( - mut encoder: E, + mut encoder: Box + Send + 'static>, resp_body: B, compression_encoding: Option, -) -> impl TryStream + is_json: bool, +) -> impl TryStream where - E: Encoder, - B: Stream>, + B: Stream>, { async_stream::stream! { let mut buf = BytesMut::with_capacity(super::consts::BUFFER_SIZE); @@ -48,12 +48,13 @@ pub fn encode( loop { match resp_body.next().await { Some(Ok(item)) => { - // 编码数据到缓冲中 - buf.reserve(super::consts::HEADER_SIZE); + if !is_json { + buf.reserve(super::consts::HEADER_SIZE); unsafe { buf.advance_mut(super::consts::HEADER_SIZE); + } } - + // 编码数据到缓冲中 if enable_compress { uncompression_buf.clear(); @@ -66,16 +67,21 @@ pub fn encode( } else { encoder.encode(item, &mut EncodeBuf::new(&mut buf)).map_err(|_e| crate::status::Status::new(crate::status::Code::Internal, "encode error".to_string())); } - - - let len = buf.len() - super::consts::HEADER_SIZE; - { + let result=match is_json{ + true=>{ + buf.clone() + } + false=>{ + let len = buf.len() - super::consts::HEADER_SIZE; + { let mut buf = &mut buf[..super::consts::HEADER_SIZE]; buf.put_u8(enable_compress as u8); buf.put_u32(len as u32); - } - - yield Ok(buf.split_to(len + super::consts::HEADER_SIZE).freeze()); + } + buf.split_to(len + super::consts::HEADER_SIZE) + } + }; + yield Ok(result.freeze()); }, Some(Err(err)) => yield Err(err.into()), None => break, @@ -85,28 +91,28 @@ pub fn encode( } pub fn encode_server( - encoder: E, + encoder: Box + Send + 'static>, body: B, compression_encoding: Option, -) -> EncodeBody>> + is_json: bool, +) -> EncodeBody>> where - E: Encoder, - B: Stream>, + B: Stream>, { - let s = encode(encoder, body, compression_encoding).into_stream(); + let s = encode(encoder, body, compression_encoding, is_json).into_stream(); EncodeBody::new_server(s) } pub fn encode_client( - encoder: E, + encoder: Box + Send + 'static>, body: B, compression_encoding: Option, -) -> EncodeBody>> + is_json: bool, +) -> EncodeBody>> where - E: Encoder, - B: Stream, + B: Stream, { - let s = encode(encoder, body.map(Ok), compression_encoding).into_stream(); + let s = encode(encoder, body.map(Ok), compression_encoding, is_json).into_stream(); EncodeBody::new_client(s) } @@ -115,6 +121,7 @@ enum Role { Server, Client, } + #[pin_project] pub struct EncodeBody { #[pin] @@ -146,7 +153,7 @@ impl EncodeBody { impl Body for EncodeBody where - S: Stream>, + S: Stream>, { type Data = Bytes; diff --git a/dubbo/src/triple/encode_json.rs b/dubbo/src/triple/encode_json.rs deleted file mode 100644 index e6b03162..00000000 --- a/dubbo/src/triple/encode_json.rs +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -use crate::status::Status; -use bytes::{Bytes, BytesMut}; -use futures_core::{Stream, TryStream}; -use futures_util::{StreamExt, TryStreamExt}; - -use crate::triple::codec::{EncodeBuf, Encoder}; -use crate::triple::compression::{compress, CompressionEncoding}; -use crate::triple::encode::EncodeBody; - -#[allow(unused_must_use)] -pub fn encode_json( - mut encoder: E, - resp_body: B, - compression_encoding: Option, -) -> impl TryStream - where - E: Encoder, - B: Stream>, -{ - async_stream::stream! { - let mut buf = BytesMut::with_capacity(super::consts::BUFFER_SIZE); - futures_util::pin_mut!(resp_body); - let (enable_compress, mut uncompression_buf) = match compression_encoding { - Some(CompressionEncoding::Gzip) => (true, BytesMut::with_capacity(super::consts::BUFFER_SIZE)), - None => (false, BytesMut::new()) - }; - loop { - match resp_body.next().await { - Some(Ok(item)) => { - if enable_compress { - uncompression_buf.clear(); - encoder.encode(item, &mut EncodeBuf::new(&mut uncompression_buf)) - .map_err(|_e| crate::status::Status::new(crate::status::Code::Internal, "encode error".to_string())); - - let len = uncompression_buf.len(); - compress(compression_encoding.unwrap(), &mut uncompression_buf, &mut buf, len) - .map_err(|_| crate::status::Status::new(crate::status::Code::Internal, "compress error".to_string())); - } else { - encoder.encode(item, &mut EncodeBuf::new(&mut buf)).map_err(|_e| crate::status::Status::new(crate::status::Code::Internal, "encode error".to_string())); - }; - yield Ok(buf.clone().freeze()); - }, - Some(Err(err)) => yield Err(err.into()), - None => break, - } - } - } -} - -pub fn encode_server_json( - encoder: E, - body: B, - compress: Option, -) -> EncodeBody>> - where - E: Encoder, - B: Stream>, -{ - let s = encode_json(encoder, body, compress).into_stream(); - EncodeBody::new_server(s) -} \ No newline at end of file diff --git a/dubbo/src/triple/mod.rs b/dubbo/src/triple/mod.rs index 9cc51bc9..799ac099 100644 --- a/dubbo/src/triple/mod.rs +++ b/dubbo/src/triple/mod.rs @@ -23,4 +23,3 @@ pub mod decode; pub mod encode; pub mod server; pub mod transport; -mod encode_json; diff --git a/dubbo/src/triple/server/triple.rs b/dubbo/src/triple/server/triple.rs index afe07666..aa205427 100644 --- a/dubbo/src/triple/server/triple.rs +++ b/dubbo/src/triple/server/triple.rs @@ -35,7 +35,8 @@ use crate::{ }; use dubbo_config::BusinessConfig; use crate::codegen::{ProstCodec, SerdeCodec}; -use crate::triple::encode_json::encode_server_json; +use crate::status::Status; +use crate::triple::codec::{Decoder, Encoder}; pub const GRPC_ACCEPT_ENCODING: &str = "grpc-accept-encoding"; pub const GRPC_ENCODING: &str = "grpc-encoding"; @@ -70,86 +71,56 @@ impl TripleServer B: Body + Send + 'static, B::Error: Into + Send, { - let is_json = req.headers().get("content-type").unwrap() == "application/grpc+json"; - if is_json { - let mut codec = SerdeCodec::::default(); - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; - } - - // Get grpc_encoding from http_header, decompress message. - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; - - let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, true)); - - let resp = service.call(Request::from_http(req_stream)).await; - - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - - let resp_body = encode_server_json( - codec.encoder(), - stream::once(future::ready(resp_body)).map(Ok).into_stream(), - accept_encoding, - ); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc+json"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); + let content_type = req.headers().get("content-type").cloned().unwrap_or(HeaderValue::from_str("application/json").unwrap()); + let is_json = content_type == "application/json" || content_type == "application/grpc+json"; + let (decoder, encoder): (Box + Send + 'static>, Box+Send+'static>) = match is_json { + true => { + let mut codec = SerdeCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) - } else { - let mut codec = ProstCodec::::default(); - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; + false => { + let mut codec = ProstCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } + }; + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } - // Get grpc_encoding from http_header, decompress message. - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; - - let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, false)); - - let resp = service.call(Request::from_http(req_stream)).await; - - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - - let resp_body = encode_server( - codec.encoder(), - stream::once(future::ready(resp_body)).map(Ok).into_stream(), - accept_encoding, - ); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc+proto"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); - } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) + // Get grpc_encoding from http_header, decompress message. + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; + + let req_stream = req.map(|body| Decoding::new(body, decoder, compression, is_json)); + + let resp = service.call(Request::from_http(req_stream)).await; + + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + + let resp_body = encode_server( + encoder, + stream::once(future::ready(resp_body)).map(Ok).into_stream(), + accept_encoding, + is_json, + ); + + parts.headers.insert( + http::header::CONTENT_TYPE, + content_type, + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) } pub async fn bidi_streaming( @@ -163,80 +134,53 @@ impl TripleServer B: Body + Send + 'static, B::Error: Into + Send, { - let is_json = req.headers().get("content-type").unwrap() == "application/grpc+json"; - if is_json { - let mut codec = SerdeCodec::::default(); - // Firstly, get grpc_accept_encoding from http_header, get compression - // Secondly, if server enable compression and compression is valid, this method should compress response - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; - } + let content_type = req.headers().get("content-type").cloned().unwrap_or(HeaderValue::from_str("application/json").unwrap()); + let is_json = content_type == "application/json" || content_type == "application/grpc+json"; - // Get grpc_encoding from http_header, decompress message. - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; - - let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, is_json)); - - let resp = service.call(Request::from_http(req_stream)).await; - - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - let resp_body = encode_server_json(codec.encoder(), resp_body, compression); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc+json"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); + let (decoder, encoder): (Box + Send + 'static>, Box+Send+'static>) = match is_json { + true => { + let mut codec = SerdeCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) - } else { - let mut codec = ProstCodec::::default(); - // Firstly, get grpc_accept_encoding from http_header, get compression - // Secondly, if server enable compression and compression is valid, this method should compress response - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; + false => { + let mut codec = ProstCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } + }; + // Firstly, get grpc_accept_encoding from http_header, get compression + // Secondly, if server enable compression and compression is valid, this method should compress response + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } - // Get grpc_encoding from http_header, decompress message. - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; - - let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, false)); - - let resp = service.call(Request::from_http(req_stream)).await; - - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - let resp_body = encode_server(codec.encoder(), resp_body, compression); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc+proto"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); - } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) + // Get grpc_encoding from http_header, decompress message. + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; + + let req_stream = req.map(|body| Decoding::new(body, decoder, compression, is_json)); + + let resp = service.call(Request::from_http(req_stream)).await; + + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + let resp_body = encode_server(encoder, resp_body, compression, is_json); + + parts.headers.insert( + http::header::CONTENT_TYPE, + content_type, + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) } pub async fn server_streaming( @@ -250,94 +194,60 @@ impl TripleServer B: Body + Send + 'static, B::Error: Into + Send, { - let is_json = req.headers().get("content-type").unwrap() == "application/grpc+json"; - if is_json { - let mut codec = SerdeCodec::::default(); - // Firstly, get grpc_accept_encoding from http_header, get compression - // Secondly, if server enable compression and compression is valid, this method should compress response - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; - } + let content_type = req.headers().get("content-type").cloned().unwrap_or(HeaderValue::from_str("application/json").unwrap()); + let is_json = content_type == "application/json" || content_type == "application/grpc+json"; - // Get grpc_encoding from http_header, decompress message. - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; - let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, true)); - let (parts, mut body) = Request::from_http(req_stream).into_parts(); - let msg = body.try_next().await.unwrap().ok_or_else(|| { - crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) - }); - let msg = match msg { - Ok(v) => v, - Err(err) => return err.to_http(), - }; - - let resp = service.call(Request::from_parts(parts, msg)).await; - - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - let resp_body = encode_server_json(codec.encoder(), resp_body, compression); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc+json"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); + let (decoder, encoder): (Box + Send + 'static>, Box+Send+'static>) = match is_json { + true => { + let mut codec = SerdeCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) - } else { - let mut codec = ProstCodec::::default(); - // Firstly, get grpc_accept_encoding from http_header, get compression - // Secondly, if server enable compression and compression is valid, this method should compress response - let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); - if self.compression.is_none() || accept_encoding.is_none() { - accept_encoding = None; + false => { + let mut codec = ProstCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } + }; + // Firstly, get grpc_accept_encoding from http_header, get compression + // Secondly, if server enable compression and compression is valid, this method should compress response + let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); + if self.compression.is_none() || accept_encoding.is_none() { + accept_encoding = None; + } - // Get grpc_encoding from http_header, decompress message. - let compression = match self.get_encoding_from_req(req.headers()) { - Ok(val) => val, - Err(status) => return status.to_http(), - }; - let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, false)); - let (parts, mut body) = Request::from_http(req_stream).into_parts(); - let msg = body.try_next().await.unwrap().ok_or_else(|| { - crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) - }); - let msg = match msg { - Ok(v) => v, - Err(err) => return err.to_http(), - }; - - let resp = service.call(Request::from_parts(parts, msg)).await; - - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - let resp_body = encode_server(codec.encoder(), resp_body, compression); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc+proto"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); - } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) + // Get grpc_encoding from http_header, decompress message. + let compression = match self.get_encoding_from_req(req.headers()) { + Ok(val) => val, + Err(status) => return status.to_http(), + }; + let req_stream = req.map(|body| Decoding::new(body, decoder, compression, is_json)); + let (parts, mut body) = Request::from_http(req_stream).into_parts(); + let msg = body.try_next().await.unwrap().ok_or_else(|| { + crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) + }); + let msg = match msg { + Ok(v) => v, + Err(err) => return err.to_http(), + }; + + let resp = service.call(Request::from_parts(parts, msg)).await; + + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + let resp_body = encode_server(encoder, resp_body, compression, is_json); + + parts.headers.insert( + http::header::CONTENT_TYPE, + content_type, + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) } pub async fn unary( @@ -361,77 +271,51 @@ impl TripleServer }; let content_type = req.headers().get("content-type").cloned().unwrap_or(HeaderValue::from_str("application/json").unwrap()); let is_json = content_type == "application/json" || content_type == "application/grpc+json"; - if is_json { - let mut codec = SerdeCodec::::default(); - let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, is_json)); - let (parts, mut body) = Request::from_http(req_stream).into_parts(); - let msg = body.try_next().await.unwrap().ok_or_else(|| { - crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) - }); - let msg = match msg { - Ok(v) => v, - Err(err) => return err.to_http(), - }; - - let resp = service.call(Request::from_parts(parts, msg)).await; - - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - let resp_body = encode_server_json( - codec.encoder(), - stream::once(future::ready(resp_body)).map(Ok).into_stream(), - accept_encoding, - ); - - parts.headers.insert( - http::header::CONTENT_TYPE, - content_type, - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); + + let (decoder, encoder): (Box + Send + 'static>, Box+Send+'static>) = match is_json { + true => { + let mut codec = SerdeCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) - }else { - let mut codec = ProstCodec::::default(); - let req_stream = req.map(|body| Decoding::new(body, codec.decoder(), compression, is_json)); - let (parts, mut body) = Request::from_http(req_stream).into_parts(); - let msg = body.try_next().await.unwrap().ok_or_else(|| { - crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) - }); - let msg = match msg { - Ok(v) => v, - Err(err) => return err.to_http(), - }; - - let resp = service.call(Request::from_parts(parts, msg)).await; - - let (mut parts, resp_body) = match resp { - Ok(v) => v.into_http().into_parts(), - Err(err) => return err.to_http(), - }; - let resp_body = encode_server( - codec.encoder(), - stream::once(future::ready(resp_body)).map(Ok).into_stream(), - accept_encoding, - ); - - parts.headers.insert( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/grpc+proto"), - ); - if let Some(encoding) = accept_encoding { - parts - .headers - .insert(GRPC_ENCODING, encoding.into_header_value()); + false => { + let mut codec = ProstCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) } - parts.status = http::StatusCode::OK; - http::Response::from_parts(parts, BoxBody::new(resp_body)) + }; + let req_stream = req.map(|body| Decoding::new(body, decoder, compression, is_json)); + let (parts, mut body) = Request::from_http(req_stream).into_parts(); + let msg = body.try_next().await.unwrap().ok_or_else(|| { + crate::status::Status::new(crate::status::Code::Unknown, "request wrong".to_string()) + }); + let msg = match msg { + Ok(v) => v, + Err(err) => return err.to_http(), + }; + + let resp = service.call(Request::from_parts(parts, msg)).await; + + let (mut parts, resp_body) = match resp { + Ok(v) => v.into_http().into_parts(), + Err(err) => return err.to_http(), + }; + let resp_body = encode_server( + encoder, + stream::once(future::ready(resp_body)).map(Ok).into_stream(), + accept_encoding, + is_json, + ); + + parts.headers.insert( + http::header::CONTENT_TYPE, + content_type + ); + if let Some(encoding) = accept_encoding { + parts + .headers + .insert(GRPC_ENCODING, encoding.into_header_value()); } + parts.status = http::StatusCode::OK; + http::Response::from_parts(parts, BoxBody::new(resp_body)) } fn get_encoding_from_req( diff --git a/examples/echo/src/generated/grpc.examples.echo.rs b/examples/echo/src/generated/grpc.examples.echo.rs index 57a89cee..ada1266c 100644 --- a/examples/echo/src/generated/grpc.examples.echo.rs +++ b/examples/echo/src/generated/grpc.examples.echo.rs @@ -40,7 +40,7 @@ pub mod echo_client { &mut self, request: Request, ) -> Result, dubbo::status::Status> { - let codec = dubbo::codegen::ProstCodec::< + let codec = dubbo::codegen::FakeCodec::< super::EchoRequest, super::EchoResponse, >::default(); @@ -57,7 +57,7 @@ pub mod echo_client { &mut self, request: Request, ) -> Result>, dubbo::status::Status> { - let codec = dubbo::codegen::ProstCodec::< + let codec = dubbo::codegen::FakeCodec::< super::EchoRequest, super::EchoResponse, >::default(); @@ -74,7 +74,7 @@ pub mod echo_client { &mut self, request: impl IntoStreamingRequest, ) -> Result, dubbo::status::Status> { - let codec = dubbo::codegen::ProstCodec::< + let codec = dubbo::codegen::FakeCodec::< super::EchoRequest, super::EchoResponse, >::default(); @@ -91,7 +91,7 @@ pub mod echo_client { &mut self, request: impl IntoStreamingRequest, ) -> Result>, dubbo::status::Status> { - let codec = dubbo::codegen::ProstCodec::< + let codec = dubbo::codegen::FakeCodec::< super::EchoRequest, super::EchoResponse, >::default(); From 5af48ff99e924fd81bd1302d5cdec5e118ce4522 Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Wed, 16 Aug 2023 10:02:46 -0400 Subject: [PATCH 07/11] style: Formatted the code according to the cargo fmt standard(#145) --- application.yaml | 4 +- config/src/config.rs | 3 +- config/src/consumer.rs | 43 +++-- config/src/lib.rs | 2 +- dubbo-build/src/client.rs | 1 - dubbo-build/src/server.rs | 1 - dubbo/src/codegen.rs | 2 +- dubbo/src/triple/client/triple.rs | 160 ++++++++--------- dubbo/src/triple/codec/mod.rs | 15 +- dubbo/src/triple/codec/serde_codec.rs | 1 - dubbo/src/triple/decode.rs | 33 ++-- dubbo/src/triple/encode.rs | 28 +-- dubbo/src/triple/server/triple.rs | 126 ++++++++------ examples/echo/src/echo/client.rs | 1 - examples/echo/src/example.http | 7 - .../echo/src/generated/grpc.examples.echo.rs | 163 ++++++------------ examples/greeter/src/example.http | 8 - 17 files changed, 272 insertions(+), 326 deletions(-) delete mode 100644 examples/echo/src/example.http delete mode 100644 examples/greeter/src/example.http diff --git a/application.yaml b/application.yaml index 9add3256..4b92deae 100644 --- a/application.yaml +++ b/application.yaml @@ -23,9 +23,9 @@ dubbo: interface: org.apache.dubbo.sample.tri.Greeter protocol: tri codec: proto - compress: false + compress: true - url: tri://localhost:20000 interface: grpc.examples.echo.Echo protocol: tri codec: json - compress: true \ No newline at end of file + compress: false \ No newline at end of file diff --git a/config/src/config.rs b/config/src/config.rs index 6a1a2885..106a8b1b 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -17,12 +17,11 @@ use std::{collections::HashMap, env, path::PathBuf}; -use crate::{protocol::Protocol, registry::RegistryConfig}; +use crate::{consumer::ConsumerConfig, protocol::Protocol, registry::RegistryConfig}; use dubbo_logger::tracing; use dubbo_utils::yaml_util::yaml_file_parser; use once_cell::sync::OnceCell; use serde::{Deserialize, Serialize}; -use crate::consumer::ConsumerConfig; use super::{protocol::ProtocolConfig, provider::ProviderConfig, service::ServiceConfig}; diff --git a/config/src/consumer.rs b/config/src/consumer.rs index d5ca220e..177a48c8 100644 --- a/config/src/consumer.rs +++ b/config/src/consumer.rs @@ -1,10 +1,26 @@ -use std::collections::HashMap; +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::get_global_config; use once_cell::sync::OnceCell; use serde::{Deserialize, Serialize}; -use crate::{get_global_config}; - +use std::collections::HashMap; -pub static GLOBAL_CONSUMER_CONFIG: OnceCell> = OnceCell::new(); +pub static GLOBAL_CONSUMER_CONFIG: OnceCell> = OnceCell::new(); #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct ConsumerConfig { @@ -12,21 +28,18 @@ pub struct ConsumerConfig { } impl ConsumerConfig { - pub fn get_global_consumer_config(interface:String) -> Option { - let config=GLOBAL_CONSUMER_CONFIG.get_or_init(|| { - match get_global_config().consumer.clone() { - None => { - HashMap::new() - } + pub fn get_global_consumer_config(interface: String) -> Option { + let config = + GLOBAL_CONSUMER_CONFIG.get_or_init(|| match get_global_config().consumer.clone() { + None => HashMap::new(), Some(config) => { - let mut consumers=HashMap::new(); + let mut consumers = HashMap::new(); for consumer_config in config.references { - consumers.insert(consumer_config.interface.clone(),consumer_config); + consumers.insert(consumer_config.interface.clone(), consumer_config); } consumers } - } - }); + }); config.get(interface.as_str()).cloned() } } @@ -38,4 +51,4 @@ pub struct Consumer { pub protocol: String, pub codec: String, pub compress: bool, -} \ No newline at end of file +} diff --git a/config/src/lib.rs b/config/src/lib.rs index 5804b8f8..ed4e494f 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -18,8 +18,8 @@ pub use config::*; pub mod config; +pub mod consumer; pub mod protocol; pub mod provider; pub mod registry; pub mod service; -pub mod consumer; diff --git a/dubbo-build/src/client.rs b/dubbo-build/src/client.rs index a3c2df2e..e7ad433e 100644 --- a/dubbo-build/src/client.rs +++ b/dubbo-build/src/client.rs @@ -20,7 +20,6 @@ use crate::{Method, Service}; use proc_macro2::TokenStream; use quote::{format_ident, quote}; - /// Generate service for client. /// /// This takes some `Service` and will generate a `TokenStream` that contains diff --git a/dubbo-build/src/server.rs b/dubbo-build/src/server.rs index 8b5f5a4c..9e006c7a 100644 --- a/dubbo-build/src/server.rs +++ b/dubbo-build/src/server.rs @@ -336,7 +336,6 @@ fn generate_unary( let (request, response) = method.request_response_name(proto_path, compile_well_known_types); - quote! { #[allow(non_camel_case_types)] struct #service_ident { diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index 3bf54da7..6213c2ce 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -34,7 +34,7 @@ pub use super::{ registry::{BoxRegistry, Registry}, triple::{ client::TripleClient, - codec::{prost::ProstCodec, serde_codec::SerdeCodec,Codec,FakeCodec}, + codec::{prost::ProstCodec, serde_codec::SerdeCodec, Codec, FakeCodec}, decode::Decoding, server::{ service::{ClientStreamingSvc, ServerStreamingSvc, StreamingSvc, UnarySvc}, diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index 5a9e5d0c..f4f28bcc 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -20,24 +20,25 @@ use std::str::FromStr; use futures_util::{future, stream, StreamExt, TryStreamExt}; use aws_smithy_http::body::SdkBody; +use dubbo_config::consumer::ConsumerConfig; use http::HeaderValue; use prost::Message; use serde::{Deserialize, Serialize}; -use dubbo_config::consumer::{ConsumerConfig}; use super::builder::ClientBuilder; use crate::codegen::{FakeCodec, ProstCodec, RpcInvocation, SerdeCodec}; use crate::{ - invocation::{IntoStreamingRequest, Metadata, Request, Response}, + invocation::{IntoStreamingRequest, Invocation, Metadata, Request, Response}, protocol::BoxInvoker, - triple::{codec::Codec, compression::CompressionEncoding, decode::Decoding}, + status::Status, + triple::{ + codec::{Codec, Decoder, Encoder}, + compression::CompressionEncoding, + decode::Decoding, + encode::encode, + }, }; -use crate::invocation::Invocation; -use crate::status::Status; -use crate::triple::codec::{Decoder, Encoder}; -use crate::triple::encode::encode; - #[derive(Debug, Clone, Default)] pub struct TripleClient { @@ -152,20 +153,24 @@ impl TripleClient { path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result, crate::status::Status> - where - M1: Message + Send + Sync + 'static + Serialize, - M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, + where + M1: Message + Send + Sync + 'static + Serialize, + M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); + let config = + ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); let (is_json, is_compression) = match config { - None => { (false, true) } - Some(config) => { (config.codec.clone() == "json".to_string(), config.compress) } + None => (false, true), + Some(config) => (config.codec.clone() == "json".to_string(), config.compress), }; let compression = match is_compression { - true => { self.send_compression_encoding } - false => { None } + true => self.send_compression_encoding, + false => None, }; - let (decoder, encoder): (Box + Send + 'static>, Box + Send + 'static>) = match is_json { + let (decoder, encoder): ( + Box + Send + 'static>, + Box + Send + 'static>, + ) = match is_json { true => { let mut codec = SerdeCodec::::default(); (Box::new(codec.decoder()), Box::new(codec.encoder())) @@ -176,13 +181,8 @@ impl TripleClient { } }; let req = req.map(|m| stream::once(future::ready(m))); - let body_stream = encode( - encoder, - req.into_inner().map(Ok), - compression, - is_json, - ) - .into_stream(); + let body_stream = + encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); let body = hyper::Body::wrap_stream(body_stream); let bytes = hyper::body::to_bytes(body).await.unwrap(); let sdk_body = SdkBody::from(bytes); @@ -205,12 +205,9 @@ impl TripleClient { .await .map_err(|err| crate::status::Status::from_error(err.into())); - match response { Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, decoder, compression, is_json) - }); + let resp = v.map(|body| Decoding::new(body, decoder, compression, is_json)); let (mut parts, body) = Response::from_http(resp).into_parts(); futures_util::pin_mut!(body); @@ -234,28 +231,31 @@ impl TripleClient { } } - pub async fn bidi_streaming( &mut self, - req: impl IntoStreamingRequest, + req: impl IntoStreamingRequest, _codec: FakeCodec, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result>, crate::status::Status> - where - M1: Message + Send + Sync + 'static + Serialize, - M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, + where + M1: Message + Send + Sync + 'static + Serialize, + M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); + let config = + ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); let (is_json, is_compression) = match config { - None => { (false, true) } - Some(config) => { (config.codec.clone() == "json".to_string(), config.compress) } + None => (false, true), + Some(config) => (config.codec.clone() == "json".to_string(), config.compress), }; let compression = match is_compression { - true => { self.send_compression_encoding } - false => { None } + true => self.send_compression_encoding, + false => None, }; - let (decoder, encoder): (Box + Send + 'static>, Box + Send + 'static>) = match is_json { + let (decoder, encoder): ( + Box + Send + 'static>, + Box + Send + 'static>, + ) = match is_json { true => { let mut codec = SerdeCodec::::default(); (Box::new(codec.decoder()), Box::new(codec.encoder())) @@ -266,13 +266,7 @@ impl TripleClient { } }; let req = req.into_streaming_request(); - let en = encode( - encoder, - req.into_inner().map(Ok), - compression, - is_json, - ) - .into_stream(); + let en = encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); @@ -296,9 +290,7 @@ impl TripleClient { match response { Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, decoder, compression, is_json) - }); + let resp = v.map(|body| Decoding::new(body, decoder, compression, is_json)); Ok(Response::from_http(resp)) } @@ -308,25 +300,29 @@ impl TripleClient { pub async fn client_streaming( &mut self, - req: impl IntoStreamingRequest, + req: impl IntoStreamingRequest, _codec: FakeCodec, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result, crate::status::Status> - where - M1: Message + Send + Sync + 'static + Serialize, - M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, + where + M1: Message + Send + Sync + 'static + Serialize, + M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); + let config = + ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); let (is_json, is_compression) = match config { - None => { (false, true) } - Some(config) => { (config.codec.clone() == "json".to_string(), config.compress) } + None => (false, true), + Some(config) => (config.codec.clone() == "json".to_string(), config.compress), }; let compression = match is_compression { - true => { self.send_compression_encoding } - false => { None } + true => self.send_compression_encoding, + false => None, }; - let (decoder, encoder): (Box + Send + 'static>, Box + Send + 'static>) = match is_json { + let (decoder, encoder): ( + Box + Send + 'static>, + Box + Send + 'static>, + ) = match is_json { true => { let mut codec = SerdeCodec::::default(); (Box::new(codec.decoder()), Box::new(codec.encoder())) @@ -337,13 +333,7 @@ impl TripleClient { } }; let req = req.into_streaming_request(); - let en = encode( - encoder, - req.into_inner().map(Ok), - compression, - is_json, - ) - .into_stream(); + let en = encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); @@ -368,9 +358,7 @@ impl TripleClient { match response { Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, decoder, compression, is_json) - }); + let resp = v.map(|body| Decoding::new(body, decoder, compression, is_json)); let (mut parts, body) = Response::from_http(resp).into_parts(); futures_util::pin_mut!(body); @@ -401,21 +389,25 @@ impl TripleClient { path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result>, crate::status::Status> - where - M1: Message + Send + Sync + 'static + Serialize, - M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, + where + M1: Message + Send + Sync + 'static + Serialize, + M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let config = ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); + let config = + ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); let (is_json, is_compression) = match config { - None => { (false, true) } - Some(config) => { (config.codec.clone() == "json".to_string(), config.compress) } + None => (false, true), + Some(config) => (config.codec.clone() == "json".to_string(), config.compress), }; let compression = match is_compression { - true => { self.send_compression_encoding } - false => { None } + true => self.send_compression_encoding, + false => None, }; - let (decoder, encoder): (Box + Send + 'static>, Box + Send + 'static>) = match is_json { + let (decoder, encoder): ( + Box + Send + 'static>, + Box + Send + 'static>, + ) = match is_json { true => { let mut codec = SerdeCodec::::default(); (Box::new(codec.decoder()), Box::new(codec.encoder())) @@ -426,13 +418,7 @@ impl TripleClient { } }; let req = req.map(|m| stream::once(future::ready(m))); - let en = encode( - encoder, - req.into_inner().map(Ok), - compression, - is_json, - ) - .into_stream(); + let en = encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); @@ -455,9 +441,7 @@ impl TripleClient { match response { Ok(v) => { - let resp = v.map(|body| { - Decoding::new(body, decoder, compression, is_json) - }); + let resp = v.map(|body| Decoding::new(body, decoder, compression, is_json)); Ok(Response::from_http(resp)) } diff --git a/dubbo/src/triple/codec/mod.rs b/dubbo/src/triple/codec/mod.rs index a219d8c0..1835c859 100644 --- a/dubbo/src/triple/codec/mod.rs +++ b/dubbo/src/triple/codec/mod.rs @@ -19,10 +19,9 @@ pub mod buffer; pub mod prost; pub mod serde_codec; -use std::io; -use std::marker::PhantomData; use ::prost::Message; use serde::{Deserialize, Serialize}; +use std::{io, marker::PhantomData}; pub use self::buffer::{DecodeBuf, EncodeBuf}; use crate::status::Status; @@ -34,9 +33,9 @@ pub trait Codec { type Decode: Send + 'static; /// The encoder that can encode a message. - type Encoder: Encoder + Send + 'static; + type Encoder: Encoder + Send + 'static; /// The encoder that can decode a message. - type Decoder: Decoder + Send + 'static; + type Decoder: Decoder + Send + 'static; /// Fetch the encoder. fn encoder(&mut self) -> Self::Encoder; @@ -91,10 +90,10 @@ impl Default for FakeCodec { } impl<'a, T, U> FakeTypes for FakeCodec - where - T: Message + Serialize + Send + 'static, - U: Message + Deserialize<'a> + Send + 'static, +where + T: Message + Serialize + Send + 'static, + U: Message + Deserialize<'a> + Send + 'static, { type Encode = T; type Decode = U; -} \ No newline at end of file +} diff --git a/dubbo/src/triple/codec/serde_codec.rs b/dubbo/src/triple/codec/serde_codec.rs index 60a75076..308a939a 100644 --- a/dubbo/src/triple/codec/serde_codec.rs +++ b/dubbo/src/triple/codec/serde_codec.rs @@ -87,4 +87,3 @@ impl<'a, U: Deserialize<'a>> Decoder for SerdeDecoder { Ok(Some(U::deserialize(&mut de).unwrap())) } } - diff --git a/dubbo/src/triple/decode.rs b/dubbo/src/triple/decode.rs index 47398132..875bbea9 100644 --- a/dubbo/src/triple/decode.rs +++ b/dubbo/src/triple/decode.rs @@ -33,7 +33,7 @@ type BoxBody = http_body::combinators::UnsyncBoxBody { state: State, body: BoxBody, - decoder: Box + Send + 'static>, + decoder: Box + Send + 'static>, buf: BytesMut, trailers: Option, compress: Option, @@ -50,10 +50,15 @@ enum State { } impl Decoding { - pub fn new(body: B, decoder: Box + Send + 'static>, compress: Option, is_json: bool) -> Self - where - B: Body + Send + 'static, - B::Error: Into, + pub fn new( + body: B, + decoder: Box + Send + 'static>, + compress: Option, + is_json: bool, + ) -> Self + where + B: Body + Send + 'static, + B::Error: Into, { Self { state: State::ReadHeader, @@ -103,15 +108,12 @@ impl Decoding { return Ok(None); } match self.compress { - None => { self.decompress_buf = self.buf.clone() } + None => self.decompress_buf = self.buf.clone(), Some(compress) => { let len = self.buf.len(); - if let Err(err) = decompress( - compress, - &mut self.buf, - &mut self.decompress_buf, - len, - ) { + if let Err(err) = + decompress(compress, &mut self.buf, &mut self.decompress_buf, len) + { return Err(crate::status::Status::new( crate::status::Code::Internal, err.to_string(), @@ -119,8 +121,10 @@ impl Decoding { } } } - let len=self.decompress_buf.len(); - let decoding_result = self.decoder.decode(&mut DecodeBuf::new(&mut self.decompress_buf, len)); + let len = self.decompress_buf.len(); + let decoding_result = self + .decoder + .decode(&mut DecodeBuf::new(&mut self.decompress_buf, len)); return match decoding_result { Ok(Some(r)) => { @@ -271,4 +275,3 @@ impl Stream for Decoding { (0, None) } } - diff --git a/dubbo/src/triple/encode.rs b/dubbo/src/triple/encode.rs index e06e42ae..1c971d6e 100644 --- a/dubbo/src/triple/encode.rs +++ b/dubbo/src/triple/encode.rs @@ -28,13 +28,13 @@ use crate::triple::codec::{EncodeBuf, Encoder}; #[allow(unused_must_use)] pub fn encode( - mut encoder: Box + Send + 'static>, + mut encoder: Box + Send + 'static>, resp_body: B, compression_encoding: Option, is_json: bool, -) -> impl TryStream - where - B: Stream>, +) -> impl TryStream +where + B: Stream>, { async_stream::stream! { let mut buf = BytesMut::with_capacity(super::consts::BUFFER_SIZE); @@ -91,26 +91,26 @@ pub fn encode( } pub fn encode_server( - encoder: Box + Send + 'static>, + encoder: Box + Send + 'static>, body: B, compression_encoding: Option, is_json: bool, -) -> EncodeBody>> - where - B: Stream>, +) -> EncodeBody>> +where + B: Stream>, { let s = encode(encoder, body, compression_encoding, is_json).into_stream(); EncodeBody::new_server(s) } pub fn encode_client( - encoder: Box + Send + 'static>, + encoder: Box + Send + 'static>, body: B, compression_encoding: Option, is_json: bool, -) -> EncodeBody>> - where - B: Stream, +) -> EncodeBody>> +where + B: Stream, { let s = encode(encoder, body.map(Ok), compression_encoding, is_json).into_stream(); EncodeBody::new_client(s) @@ -152,8 +152,8 @@ impl EncodeBody { } impl Body for EncodeBody - where - S: Stream>, +where + S: Stream>, { type Data = Bytes; diff --git a/dubbo/src/triple/server/triple.rs b/dubbo/src/triple/server/triple.rs index aa205427..c7f4dc42 100644 --- a/dubbo/src/triple/server/triple.rs +++ b/dubbo/src/triple/server/triple.rs @@ -15,17 +15,19 @@ * limitations under the License. */ -use std::marker::PhantomData; use futures_util::{future, stream, StreamExt, TryStreamExt}; use http::HeaderValue; use http_body::Body; use prost::Message; use serde::{Deserialize, Serialize}; +use std::marker::PhantomData; use crate::{ + codegen::{ProstCodec, SerdeCodec}, invocation::Request, + status::Status, triple::{ - codec::Codec, + codec::{Codec, Decoder, Encoder}, compression::{CompressionEncoding, COMPRESSIONS}, decode::Decoding, encode::encode_server, @@ -34,15 +36,11 @@ use crate::{ BoxBody, }; use dubbo_config::BusinessConfig; -use crate::codegen::{ProstCodec, SerdeCodec}; -use crate::status::Status; -use crate::triple::codec::{Decoder, Encoder}; pub const GRPC_ACCEPT_ENCODING: &str = "grpc-accept-encoding"; pub const GRPC_ENCODING: &str = "grpc-encoding"; -pub struct TripleServer -{ +pub struct TripleServer { _pd: PhantomData<(T, V)>, compression: Option, } @@ -57,23 +55,30 @@ impl TripleServer { } impl TripleServer - where - T: Message + for<'a> Deserialize<'a> + Default + 'static, - V: Message + Serialize + Default + 'static +where + T: Message + for<'a> Deserialize<'a> + Default + 'static, + V: Message + Serialize + Default + 'static, { pub async fn client_streaming( &mut self, mut service: S, req: http::Request, ) -> http::Response - where - S: ClientStreamingSvc, - B: Body + Send + 'static, - B::Error: Into + Send, + where + S: ClientStreamingSvc, + B: Body + Send + 'static, + B::Error: Into + Send, { - let content_type = req.headers().get("content-type").cloned().unwrap_or(HeaderValue::from_str("application/json").unwrap()); + let content_type = req + .headers() + .get("content-type") + .cloned() + .unwrap_or(HeaderValue::from_str("application/json").unwrap()); let is_json = content_type == "application/json" || content_type == "application/grpc+json"; - let (decoder, encoder): (Box + Send + 'static>, Box+Send+'static>) = match is_json { + let (decoder, encoder): ( + Box + Send + 'static>, + Box + Send + 'static>, + ) = match is_json { true => { let mut codec = SerdeCodec::::default(); (Box::new(codec.decoder()), Box::new(codec.encoder())) @@ -110,10 +115,9 @@ impl TripleServer is_json, ); - parts.headers.insert( - http::header::CONTENT_TYPE, - content_type, - ); + parts + .headers + .insert(http::header::CONTENT_TYPE, content_type); if let Some(encoding) = accept_encoding { parts .headers @@ -128,16 +132,23 @@ impl TripleServer mut service: S, req: http::Request, ) -> http::Response - where - S: StreamingSvc, - S::ResponseStream: Send + 'static, - B: Body + Send + 'static, - B::Error: Into + Send, + where + S: StreamingSvc, + S::ResponseStream: Send + 'static, + B: Body + Send + 'static, + B::Error: Into + Send, { - let content_type = req.headers().get("content-type").cloned().unwrap_or(HeaderValue::from_str("application/json").unwrap()); + let content_type = req + .headers() + .get("content-type") + .cloned() + .unwrap_or(HeaderValue::from_str("application/json").unwrap()); let is_json = content_type == "application/json" || content_type == "application/grpc+json"; - let (decoder, encoder): (Box + Send + 'static>, Box+Send+'static>) = match is_json { + let (decoder, encoder): ( + Box + Send + 'static>, + Box + Send + 'static>, + ) = match is_json { true => { let mut codec = SerdeCodec::::default(); (Box::new(codec.decoder()), Box::new(codec.encoder())) @@ -170,10 +181,9 @@ impl TripleServer }; let resp_body = encode_server(encoder, resp_body, compression, is_json); - parts.headers.insert( - http::header::CONTENT_TYPE, - content_type, - ); + parts + .headers + .insert(http::header::CONTENT_TYPE, content_type); if let Some(encoding) = accept_encoding { parts .headers @@ -188,16 +198,23 @@ impl TripleServer mut service: S, req: http::Request, ) -> http::Response - where - S: ServerStreamingSvc, - S::ResponseStream: Send + 'static, - B: Body + Send + 'static, - B::Error: Into + Send, + where + S: ServerStreamingSvc, + S::ResponseStream: Send + 'static, + B: Body + Send + 'static, + B::Error: Into + Send, { - let content_type = req.headers().get("content-type").cloned().unwrap_or(HeaderValue::from_str("application/json").unwrap()); + let content_type = req + .headers() + .get("content-type") + .cloned() + .unwrap_or(HeaderValue::from_str("application/json").unwrap()); let is_json = content_type == "application/json" || content_type == "application/grpc+json"; - let (decoder, encoder): (Box + Send + 'static>, Box+Send+'static>) = match is_json { + let (decoder, encoder): ( + Box + Send + 'static>, + Box + Send + 'static>, + ) = match is_json { true => { let mut codec = SerdeCodec::::default(); (Box::new(codec.decoder()), Box::new(codec.encoder())) @@ -237,10 +254,9 @@ impl TripleServer }; let resp_body = encode_server(encoder, resp_body, compression, is_json); - parts.headers.insert( - http::header::CONTENT_TYPE, - content_type, - ); + parts + .headers + .insert(http::header::CONTENT_TYPE, content_type); if let Some(encoding) = accept_encoding { parts .headers @@ -255,10 +271,10 @@ impl TripleServer mut service: S, req: http::Request, ) -> http::Response - where - S: UnarySvc, - B: Body + Send + 'static, - B::Error: Into + Send, + where + S: UnarySvc, + B: Body + Send + 'static, + B::Error: Into + Send, { let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); if self.compression.is_none() || accept_encoding.is_none() { @@ -269,10 +285,17 @@ impl TripleServer Ok(val) => val, Err(status) => return status.to_http(), }; - let content_type = req.headers().get("content-type").cloned().unwrap_or(HeaderValue::from_str("application/json").unwrap()); + let content_type = req + .headers() + .get("content-type") + .cloned() + .unwrap_or(HeaderValue::from_str("application/json").unwrap()); let is_json = content_type == "application/json" || content_type == "application/grpc+json"; - let (decoder, encoder): (Box + Send + 'static>, Box+Send+'static>) = match is_json { + let (decoder, encoder): ( + Box + Send + 'static>, + Box + Send + 'static>, + ) = match is_json { true => { let mut codec = SerdeCodec::::default(); (Box::new(codec.decoder()), Box::new(codec.encoder())) @@ -305,10 +328,9 @@ impl TripleServer is_json, ); - parts.headers.insert( - http::header::CONTENT_TYPE, - content_type - ); + parts + .headers + .insert(http::header::CONTENT_TYPE, content_type); if let Some(encoding) = accept_encoding { parts .headers diff --git a/examples/echo/src/echo/client.rs b/examples/echo/src/echo/client.rs index 206796c1..1a210007 100644 --- a/examples/echo/src/echo/client.rs +++ b/examples/echo/src/echo/client.rs @@ -28,7 +28,6 @@ impl Filter for FakeFilter { } } - #[tokio::main] async fn main() { dubbo_logger::init(); diff --git a/examples/echo/src/example.http b/examples/echo/src/example.http deleted file mode 100644 index 4cba3332..00000000 --- a/examples/echo/src/example.http +++ /dev/null @@ -1,7 +0,0 @@ -POST /grpc.examples.echo.Echo/UnaryEcho HTTP/1.1 -Host: 127.0.0.1:8888 -Content-Type: application/json - -{ - "message":"1" -} \ No newline at end of file diff --git a/examples/echo/src/generated/grpc.examples.echo.rs b/examples/echo/src/generated/grpc.examples.echo.rs index ada1266c..0ddaf893 100644 --- a/examples/echo/src/generated/grpc.examples.echo.rs +++ b/examples/echo/src/generated/grpc.examples.echo.rs @@ -40,16 +40,12 @@ pub mod echo_client { &mut self, request: Request, ) -> Result, dubbo::status::Status> { - let codec = dubbo::codegen::FakeCodec::< - super::EchoRequest, - super::EchoResponse, - >::default(); + let codec = + dubbo::codegen::FakeCodec::::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("UnaryEcho")); - let path = http::uri::PathAndQuery::from_static( - "/grpc.examples.echo.Echo/UnaryEcho", - ); + let path = http::uri::PathAndQuery::from_static("/grpc.examples.echo.Echo/UnaryEcho"); self.inner.unary(request, codec, path, invocation).await } /// ServerStreamingEcho is server side streaming. @@ -57,51 +53,51 @@ pub mod echo_client { &mut self, request: Request, ) -> Result>, dubbo::status::Status> { - let codec = dubbo::codegen::FakeCodec::< - super::EchoRequest, - super::EchoResponse, - >::default(); + let codec = + dubbo::codegen::FakeCodec::::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("ServerStreamingEcho")); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/ServerStreamingEcho", ); - self.inner.server_streaming(request, codec, path, invocation).await + self.inner + .server_streaming(request, codec, path, invocation) + .await } /// ClientStreamingEcho is client side streaming. pub async fn client_streaming_echo( &mut self, request: impl IntoStreamingRequest, ) -> Result, dubbo::status::Status> { - let codec = dubbo::codegen::FakeCodec::< - super::EchoRequest, - super::EchoResponse, - >::default(); + let codec = + dubbo::codegen::FakeCodec::::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("ClientStreamingEcho")); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/ClientStreamingEcho", ); - self.inner.client_streaming(request, codec, path, invocation).await + self.inner + .client_streaming(request, codec, path, invocation) + .await } /// BidirectionalStreamingEcho is bidi streaming. pub async fn bidirectional_streaming_echo( &mut self, request: impl IntoStreamingRequest, ) -> Result>, dubbo::status::Status> { - let codec = dubbo::codegen::FakeCodec::< - super::EchoRequest, - super::EchoResponse, - >::default(); + let codec = + dubbo::codegen::FakeCodec::::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("BidirectionalStreamingEcho")); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/BidirectionalStreamingEcho", ); - self.inner.bidi_streaming(request, codec, path, invocation).await + self.inner + .bidi_streaming(request, codec, path, invocation) + .await } } } @@ -118,9 +114,7 @@ pub mod echo_server { request: Request, ) -> Result, dubbo::status::Status>; ///Server streaming response type for the ServerStreamingEcho method. - type ServerStreamingEchoStream: futures_util::Stream< - Item = Result, - > + type ServerStreamingEchoStream: futures_util::Stream> + Send + 'static; /// ServerStreamingEcho is server side streaming. @@ -134,19 +128,14 @@ pub mod echo_server { request: Request>, ) -> Result, dubbo::status::Status>; ///Server streaming response type for the BidirectionalStreamingEcho method. - type BidirectionalStreamingEchoStream: futures_util::Stream< - Item = Result, - > + type BidirectionalStreamingEchoStream: futures_util::Stream> + Send + 'static; /// BidirectionalStreamingEcho is bidi streaming. async fn bidirectional_streaming_echo( &self, request: Request>, - ) -> Result< - Response, - dubbo::status::Status, - >; + ) -> Result, dubbo::status::Status>; } /// Echo is the echo service. #[derive(Debug)] @@ -176,10 +165,7 @@ pub mod echo_server { type Response = http::Response; type Error = std::convert::Infallible; type Future = BoxFuture; - fn poll_ready( - &mut self, - _cx: &mut Context<'_>, - ) -> Poll> { + fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { Poll::Ready(Ok(())) } fn call(&mut self, req: http::Request) -> Self::Future { @@ -192,24 +178,16 @@ pub mod echo_server { } impl UnarySvc for UnaryEchoServer { type Response = super::EchoResponse; - type Future = BoxFuture< - Response, - dubbo::status::Status, - >; - fn call( - &mut self, - request: Request, - ) -> Self::Future { + type Future = BoxFuture, dubbo::status::Status>; + fn call(&mut self, request: Request) -> Self::Future { let inner = self.inner.0.clone(); let fut = async move { inner.unary_echo(request).await }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::< - super::EchoRequest, - super::EchoResponse, - >::new(); + let mut server = + TripleServer::::new(); let res = server.unary(UnaryEchoServer { inner }, req).await; Ok(res) }; @@ -220,30 +198,20 @@ pub mod echo_server { struct ServerStreamingEchoServer { inner: _Inner, } - impl ServerStreamingSvc - for ServerStreamingEchoServer { + impl ServerStreamingSvc for ServerStreamingEchoServer { type Response = super::EchoResponse; type ResponseStream = T::ServerStreamingEchoStream; - type Future = BoxFuture< - Response, - dubbo::status::Status, - >; - fn call( - &mut self, - request: Request, - ) -> Self::Future { + type Future = + BoxFuture, dubbo::status::Status>; + fn call(&mut self, request: Request) -> Self::Future { let inner = self.inner.0.clone(); - let fut = async move { - inner.server_streaming_echo(request).await - }; + let fut = async move { inner.server_streaming_echo(request).await }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::< - super::EchoRequest, - super::EchoResponse, - >::new(); + let mut server = + TripleServer::::new(); let res = server .server_streaming(ServerStreamingEchoServer { inner }, req) .await; @@ -256,29 +224,21 @@ pub mod echo_server { struct ClientStreamingEchoServer { inner: _Inner, } - impl ClientStreamingSvc - for ClientStreamingEchoServer { + impl ClientStreamingSvc for ClientStreamingEchoServer { type Response = super::EchoResponse; - type Future = BoxFuture< - Response, - dubbo::status::Status, - >; + type Future = BoxFuture, dubbo::status::Status>; fn call( &mut self, request: Request>, ) -> Self::Future { let inner = self.inner.0.clone(); - let fut = async move { - inner.client_streaming_echo(request).await - }; + let fut = async move { inner.client_streaming_echo(request).await }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::< - super::EchoRequest, - super::EchoResponse, - >::new(); + let mut server = + TripleServer::::new(); let res = server .client_streaming(ClientStreamingEchoServer { inner }, req) .await; @@ -291,54 +251,39 @@ pub mod echo_server { struct BidirectionalStreamingEchoServer { inner: _Inner, } - impl StreamingSvc - for BidirectionalStreamingEchoServer { + impl StreamingSvc for BidirectionalStreamingEchoServer { type Response = super::EchoResponse; type ResponseStream = T::BidirectionalStreamingEchoStream; - type Future = BoxFuture< - Response, - dubbo::status::Status, - >; + type Future = + BoxFuture, dubbo::status::Status>; fn call( &mut self, request: Request>, ) -> Self::Future { let inner = self.inner.0.clone(); - let fut = async move { - inner.bidirectional_streaming_echo(request).await - }; + let fut = + async move { inner.bidirectional_streaming_echo(request).await }; Box::pin(fut) } } let fut = async move { - let mut server = TripleServer::< - super::EchoRequest, - super::EchoResponse, - >::new(); + let mut server = + TripleServer::::new(); let res = server - .bidi_streaming( - BidirectionalStreamingEchoServer { - inner, - }, - req, - ) + .bidi_streaming(BidirectionalStreamingEchoServer { inner }, req) .await; Ok(res) }; Box::pin(fut) } - _ => { - Box::pin(async move { - Ok( - http::Response::builder() - .status(200) - .header("grpc-status", "12") - .header("content-type", "application/grpc") - .body(empty_body()) - .unwrap(), - ) - }) - } + _ => Box::pin(async move { + Ok(http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap()) + }), } } } diff --git a/examples/greeter/src/example.http b/examples/greeter/src/example.http deleted file mode 100644 index c7368068..00000000 --- a/examples/greeter/src/example.http +++ /dev/null @@ -1,8 +0,0 @@ -POST /org.apache.dubbo.sample.tri.Greeter/greet HTTP/1.1 -Host: 127.0.0.1:8888 -Content-Type: application/json - -{ - "name":"hello!This is a test for unary" -} - From 1f041b27ceb8b4652d94313f2ea749cec6ab73fe Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Wed, 16 Aug 2023 10:17:46 -0400 Subject: [PATCH 08/11] perf: Resolved the warnings from cargo check(#145) --- dubbo/src/triple/client/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index 06ecd627..9dae0f93 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -59,7 +59,7 @@ impl ClientBuilder { connector: "", directory: Some(Box::new(StaticDirectory::new(&host))), direct: true, - host: host.clone().to_string(), + host: host.to_string(), } } From 3f5c1354d926f9e3b4b7cee44786ca2a5933a4ef Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Wed, 16 Aug 2023 10:59:37 -0400 Subject: [PATCH 09/11] perf: Optimized the code structure and removed redundant code(#145) --- dubbo-build/src/client.rs | 9 --- dubbo-build/src/server.rs | 7 -- dubbo/src/codegen.rs | 2 +- dubbo/src/triple/client/triple.rs | 72 +++++++------------ dubbo/src/triple/codec/mod.rs | 29 +------- dubbo/src/triple/server/triple.rs | 48 ++----------- .../echo/src/generated/grpc.examples.echo.rs | 22 ++---- 7 files changed, 39 insertions(+), 150 deletions(-) diff --git a/dubbo-build/src/client.rs b/dubbo-build/src/client.rs index e7ad433e..af32b64b 100644 --- a/dubbo-build/src/client.rs +++ b/dubbo-build/src/client.rs @@ -174,14 +174,12 @@ fn generate_unary( &mut self, request: Request<#request>, ) -> Result, dubbo::status::Status> { - let codec = dubbo::codegen::FakeCodec::<#request, #response>::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from(#service_unique_name)) .with_method_name(String::from(#method_name)); let path = http::uri::PathAndQuery::from_static(#path); self.inner.unary( request, - codec, path, invocation, ).await @@ -205,15 +203,12 @@ fn generate_server_streaming( &mut self, request: Request<#request>, ) -> Result>, dubbo::status::Status> { - - let codec = dubbo::codegen::FakeCodec::<#request, #response>::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from(#service_unique_name)) .with_method_name(String::from(#method_name)); let path = http::uri::PathAndQuery::from_static(#path); self.inner.server_streaming( request, - codec, path, invocation, ).await @@ -237,14 +232,12 @@ fn generate_client_streaming( &mut self, request: impl IntoStreamingRequest ) -> Result, dubbo::status::Status> { - let codec = dubbo::codegen::FakeCodec::<#request, #response>::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from(#service_unique_name)) .with_method_name(String::from(#method_name)); let path = http::uri::PathAndQuery::from_static(#path); self.inner.client_streaming( request, - codec, path, invocation, ).await @@ -268,14 +261,12 @@ fn generate_streaming( &mut self, request: impl IntoStreamingRequest ) -> Result>, dubbo::status::Status> { - let codec = dubbo::codegen::FakeCodec::<#request, #response>::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from(#service_unique_name)) .with_method_name(String::from(#method_name)); let path = http::uri::PathAndQuery::from_static(#path); self.inner.bidi_streaming( request, - codec, path, invocation, ).await diff --git a/dubbo-build/src/server.rs b/dubbo-build/src/server.rs index 9e006c7a..6e8c3be5 100644 --- a/dubbo-build/src/server.rs +++ b/dubbo-build/src/server.rs @@ -21,8 +21,6 @@ use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{Ident, Lit, LitStr}; -pub const CODEC_PATH: &str = "dubbo::codegen::ProstCodec"; - /// Generate service for Server. /// /// This takes some `Service` and will generate a `TokenStream` that contains @@ -370,8 +368,6 @@ fn generate_server_streaming( method_ident: Ident, server_trait: Ident, ) -> TokenStream { - let _codec_name = syn::parse_str::(CODEC_PATH).unwrap(); - let service_ident = quote::format_ident!("{}Server", method.identifier()); let (request, response) = method.request_response_name(proto_path, compile_well_known_types); @@ -417,7 +413,6 @@ fn generate_client_streaming( let service_ident = quote::format_ident!("{}Server", method.identifier()); let (request, response) = method.request_response_name(proto_path, compile_well_known_types); - let _codec_name = syn::parse_str::(CODEC_PATH).unwrap(); quote! { #[allow(non_camel_case_types)] @@ -457,8 +452,6 @@ fn generate_streaming( method_ident: Ident, server_trait: Ident, ) -> TokenStream { - let _codec_name = syn::parse_str::(CODEC_PATH).unwrap(); - let service_ident = quote::format_ident!("{}Server", method.identifier()); let (request, response) = method.request_response_name(proto_path, compile_well_known_types); diff --git a/dubbo/src/codegen.rs b/dubbo/src/codegen.rs index 6213c2ce..8d95c21b 100644 --- a/dubbo/src/codegen.rs +++ b/dubbo/src/codegen.rs @@ -34,7 +34,7 @@ pub use super::{ registry::{BoxRegistry, Registry}, triple::{ client::TripleClient, - codec::{prost::ProstCodec, serde_codec::SerdeCodec, Codec, FakeCodec}, + codec::{prost::ProstCodec, serde_codec::SerdeCodec, Codec}, decode::Decoding, server::{ service::{ClientStreamingSvc, ServerStreamingSvc, StreamingSvc, UnarySvc}, diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index f4f28bcc..a81ebfcb 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -26,7 +26,7 @@ use prost::Message; use serde::{Deserialize, Serialize}; use super::builder::ClientBuilder; -use crate::codegen::{FakeCodec, ProstCodec, RpcInvocation, SerdeCodec}; +use crate::codegen::{ProstCodec, RpcInvocation, SerdeCodec}; use crate::{ invocation::{IntoStreamingRequest, Invocation, Metadata, Request, Response}, @@ -149,7 +149,6 @@ impl TripleClient { pub async fn unary( &mut self, req: Request, - _codec: FakeCodec, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result, crate::status::Status> @@ -170,16 +169,7 @@ impl TripleClient { let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, - ) = match is_json { - true => { - let mut codec = SerdeCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - false => { - let mut codec = ProstCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - }; + ) = get_codec(is_json); let req = req.map(|m| stream::once(future::ready(m))); let body_stream = encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); @@ -234,7 +224,6 @@ impl TripleClient { pub async fn bidi_streaming( &mut self, req: impl IntoStreamingRequest, - _codec: FakeCodec, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result>, crate::status::Status> @@ -255,16 +244,7 @@ impl TripleClient { let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, - ) = match is_json { - true => { - let mut codec = SerdeCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - false => { - let mut codec = ProstCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - }; + ) = get_codec(is_json); let req = req.into_streaming_request(); let en = encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); let body = hyper::Body::wrap_stream(en); @@ -301,7 +281,6 @@ impl TripleClient { pub async fn client_streaming( &mut self, req: impl IntoStreamingRequest, - _codec: FakeCodec, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result, crate::status::Status> @@ -322,16 +301,7 @@ impl TripleClient { let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, - ) = match is_json { - true => { - let mut codec = SerdeCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - false => { - let mut codec = ProstCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - }; + ) = get_codec(is_json); let req = req.into_streaming_request(); let en = encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); let body = hyper::Body::wrap_stream(en); @@ -385,7 +355,6 @@ impl TripleClient { pub async fn server_streaming( &mut self, req: Request, - _codec: FakeCodec, path: http::uri::PathAndQuery, invocation: RpcInvocation, ) -> Result>, crate::status::Status> @@ -407,16 +376,7 @@ impl TripleClient { let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, - ) = match is_json { - true => { - let mut codec = SerdeCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - false => { - let mut codec = ProstCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - }; + ) = get_codec(is_json); let req = req.map(|m| stream::once(future::ready(m))); let en = encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); let body = hyper::Body::wrap_stream(en); @@ -449,3 +409,25 @@ impl TripleClient { } } } + +pub fn get_codec( + is_json: bool, +) -> ( + Box + Send + 'static>, + Box + Send + 'static>, +) +where + M1: Message + Send + Sync + 'static + Serialize, + M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, +{ + match is_json { + true => { + let mut codec = SerdeCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) + } + false => { + let mut codec = ProstCodec::::default(); + (Box::new(codec.decoder()), Box::new(codec.encoder())) + } + } +} diff --git a/dubbo/src/triple/codec/mod.rs b/dubbo/src/triple/codec/mod.rs index 1835c859..2ba79865 100644 --- a/dubbo/src/triple/codec/mod.rs +++ b/dubbo/src/triple/codec/mod.rs @@ -19,9 +19,7 @@ pub mod buffer; pub mod prost; pub mod serde_codec; -use ::prost::Message; -use serde::{Deserialize, Serialize}; -use std::{io, marker::PhantomData}; +use std::io; pub use self::buffer::{DecodeBuf, EncodeBuf}; use crate::status::Status; @@ -72,28 +70,3 @@ pub trait Decoder { /// for you. fn decode(&mut self, src: &mut DecodeBuf<'_>) -> Result, Self::Error>; } - -trait FakeTypes { - type Encode: Send + 'static; - type Decode: Send + 'static; -} - -#[derive(Debug)] -pub struct FakeCodec { - _pd: PhantomData<(T, U)>, -} - -impl Default for FakeCodec { - fn default() -> Self { - Self { _pd: PhantomData } - } -} - -impl<'a, T, U> FakeTypes for FakeCodec -where - T: Message + Serialize + Send + 'static, - U: Message + Deserialize<'a> + Send + 'static, -{ - type Encode = T; - type Decode = U; -} diff --git a/dubbo/src/triple/server/triple.rs b/dubbo/src/triple/server/triple.rs index c7f4dc42..e6d92fc0 100644 --- a/dubbo/src/triple/server/triple.rs +++ b/dubbo/src/triple/server/triple.rs @@ -23,11 +23,11 @@ use serde::{Deserialize, Serialize}; use std::marker::PhantomData; use crate::{ - codegen::{ProstCodec, SerdeCodec}, invocation::Request, status::Status, triple::{ - codec::{Codec, Decoder, Encoder}, + client::triple::get_codec, + codec::{Decoder, Encoder}, compression::{CompressionEncoding, COMPRESSIONS}, decode::Decoding, encode::encode_server, @@ -78,16 +78,7 @@ where let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, - ) = match is_json { - true => { - let mut codec = SerdeCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - false => { - let mut codec = ProstCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - }; + ) = get_codec(is_json); let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); if self.compression.is_none() || accept_encoding.is_none() { accept_encoding = None; @@ -148,16 +139,7 @@ where let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, - ) = match is_json { - true => { - let mut codec = SerdeCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - false => { - let mut codec = ProstCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - }; + ) = get_codec(is_json); // Firstly, get grpc_accept_encoding from http_header, get compression // Secondly, if server enable compression and compression is valid, this method should compress response let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); @@ -214,16 +196,7 @@ where let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, - ) = match is_json { - true => { - let mut codec = SerdeCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - false => { - let mut codec = ProstCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - }; + ) = get_codec(is_json); // Firstly, get grpc_accept_encoding from http_header, get compression // Secondly, if server enable compression and compression is valid, this method should compress response let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); @@ -295,16 +268,7 @@ where let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, - ) = match is_json { - true => { - let mut codec = SerdeCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - false => { - let mut codec = ProstCodec::::default(); - (Box::new(codec.decoder()), Box::new(codec.encoder())) - } - }; + ) = get_codec(is_json); let req_stream = req.map(|body| Decoding::new(body, decoder, compression, is_json)); let (parts, mut body) = Request::from_http(req_stream).into_parts(); let msg = body.try_next().await.unwrap().ok_or_else(|| { diff --git a/examples/echo/src/generated/grpc.examples.echo.rs b/examples/echo/src/generated/grpc.examples.echo.rs index 0ddaf893..0a746559 100644 --- a/examples/echo/src/generated/grpc.examples.echo.rs +++ b/examples/echo/src/generated/grpc.examples.echo.rs @@ -40,64 +40,50 @@ pub mod echo_client { &mut self, request: Request, ) -> Result, dubbo::status::Status> { - let codec = - dubbo::codegen::FakeCodec::::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("UnaryEcho")); let path = http::uri::PathAndQuery::from_static("/grpc.examples.echo.Echo/UnaryEcho"); - self.inner.unary(request, codec, path, invocation).await + self.inner.unary(request, path, invocation).await } /// ServerStreamingEcho is server side streaming. pub async fn server_streaming_echo( &mut self, request: Request, ) -> Result>, dubbo::status::Status> { - let codec = - dubbo::codegen::FakeCodec::::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("ServerStreamingEcho")); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/ServerStreamingEcho", ); - self.inner - .server_streaming(request, codec, path, invocation) - .await + self.inner.server_streaming(request, path, invocation).await } /// ClientStreamingEcho is client side streaming. pub async fn client_streaming_echo( &mut self, request: impl IntoStreamingRequest, ) -> Result, dubbo::status::Status> { - let codec = - dubbo::codegen::FakeCodec::::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("ClientStreamingEcho")); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/ClientStreamingEcho", ); - self.inner - .client_streaming(request, codec, path, invocation) - .await + self.inner.client_streaming(request, path, invocation).await } /// BidirectionalStreamingEcho is bidi streaming. pub async fn bidirectional_streaming_echo( &mut self, request: impl IntoStreamingRequest, ) -> Result>, dubbo::status::Status> { - let codec = - dubbo::codegen::FakeCodec::::default(); let invocation = RpcInvocation::default() .with_service_unique_name(String::from("grpc.examples.echo.Echo")) .with_method_name(String::from("BidirectionalStreamingEcho")); let path = http::uri::PathAndQuery::from_static( "/grpc.examples.echo.Echo/BidirectionalStreamingEcho", ); - self.inner - .bidi_streaming(request, codec, path, invocation) - .await + self.inner.bidi_streaming(request, path, invocation).await } } } From 079160085250ce5f0434be35d585fe2d0004fb49 Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Thu, 17 Aug 2023 14:32:44 -0400 Subject: [PATCH 10/11] perf: Optimized the configuration format as well as the configuration loading method.(#145) --- application.yaml | 16 ++++----- config/src/client.rs | 38 +++++++++++++++++++++ config/src/config.rs | 6 ++-- config/src/consumer.rs | 54 ------------------------------ config/src/lib.rs | 2 +- dubbo-build/src/server.rs | 2 -- dubbo/src/triple/client/builder.rs | 9 +++++ dubbo/src/triple/client/triple.rs | 27 +++++---------- dubbo/src/triple/server/triple.rs | 38 ++++++++++----------- 9 files changed, 85 insertions(+), 107 deletions(-) create mode 100644 config/src/client.rs delete mode 100644 config/src/consumer.rs diff --git a/application.yaml b/application.yaml index 4b92deae..2f93a2d1 100644 --- a/application.yaml +++ b/application.yaml @@ -17,15 +17,11 @@ dubbo: group: test protocol: triple interface: org.apache.dubbo.sample.tri.Greeter + client: + codec: proto + compress: true consumer: references: - - url: tri://localhost:20000 - interface: org.apache.dubbo.sample.tri.Greeter - protocol: tri - codec: proto - compress: true - - url: tri://localhost:20000 - interface: grpc.examples.echo.Echo - protocol: tri - codec: json - compress: false \ No newline at end of file + GreeterClientImpl: + url: tri://localhost:20000 + protocol: tri \ No newline at end of file diff --git a/config/src/client.rs b/config/src/client.rs new file mode 100644 index 00000000..08a00f1f --- /dev/null +++ b/config/src/client.rs @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +use crate::get_global_config; +use serde::{Deserialize, Serialize}; + +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct ClientConfig { + pub codec: String, + pub compress: bool, +} + +impl ClientConfig { + pub fn get_codec_and_compress() -> (bool, bool) { + let config = get_global_config().client.clone(); + match config { + None => (false, true), + Some(cfg) => ( + cfg.codec == "json".to_string().clone(), + cfg.compress.clone(), + ), + } + } +} diff --git a/config/src/config.rs b/config/src/config.rs index 106a8b1b..4eb076d2 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -17,7 +17,7 @@ use std::{collections::HashMap, env, path::PathBuf}; -use crate::{consumer::ConsumerConfig, protocol::Protocol, registry::RegistryConfig}; +use crate::{client::ClientConfig, protocol::Protocol, registry::RegistryConfig}; use dubbo_logger::tracing; use dubbo_utils::yaml_util::yaml_file_parser; use once_cell::sync::OnceCell; @@ -45,7 +45,7 @@ pub struct RootConfig { pub registries: HashMap, #[serde(default)] - pub consumer: Option, + pub client: Option, #[serde(default)] pub data: HashMap, @@ -66,7 +66,7 @@ impl RootConfig { protocols: HashMap::new(), registries: HashMap::new(), provider: ProviderConfig::new(), - consumer: None, + client: None, data: HashMap::new(), } } diff --git a/config/src/consumer.rs b/config/src/consumer.rs deleted file mode 100644 index 177a48c8..00000000 --- a/config/src/consumer.rs +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::get_global_config; -use once_cell::sync::OnceCell; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; - -pub static GLOBAL_CONSUMER_CONFIG: OnceCell> = OnceCell::new(); - -#[derive(Default, Debug, Clone, Serialize, Deserialize)] -pub struct ConsumerConfig { - pub references: Vec, -} - -impl ConsumerConfig { - pub fn get_global_consumer_config(interface: String) -> Option { - let config = - GLOBAL_CONSUMER_CONFIG.get_or_init(|| match get_global_config().consumer.clone() { - None => HashMap::new(), - Some(config) => { - let mut consumers = HashMap::new(); - for consumer_config in config.references { - consumers.insert(consumer_config.interface.clone(), consumer_config); - } - consumers - } - }); - config.get(interface.as_str()).cloned() - } -} - -#[derive(Default, Debug, Clone, Serialize, Deserialize)] -pub struct Consumer { - pub url: String, - pub interface: String, - pub protocol: String, - pub codec: String, - pub compress: bool, -} diff --git a/config/src/lib.rs b/config/src/lib.rs index ed4e494f..adfe307a 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -17,8 +17,8 @@ pub use config::*; +pub mod client; pub mod config; -pub mod consumer; pub mod protocol; pub mod provider; pub mod registry; diff --git a/dubbo-build/src/server.rs b/dubbo-build/src/server.rs index 6e8c3be5..3ccb52ad 100644 --- a/dubbo-build/src/server.rs +++ b/dubbo-build/src/server.rs @@ -328,8 +328,6 @@ fn generate_unary( method_ident: Ident, server_trait: Ident, ) -> TokenStream { - // let codec_name = syn::parse_str::(CODEC_PATH).unwrap(); - let service_ident = quote::format_ident!("{}Server", method.identifier()); let (request, response) = method.request_response_name(proto_path, compile_well_known_types); diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index 9dae0f93..a3c3c97c 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -27,6 +27,7 @@ use crate::{ use aws_smithy_http::body::SdkBody; use dubbo_base::Url; +use dubbo_config::client::ClientConfig; use super::TripleClient; @@ -40,26 +41,34 @@ pub struct ClientBuilder { directory: Option>, pub direct: bool, host: String, + pub codec_is_json: bool, + pub is_compress: bool, } impl ClientBuilder { pub fn new() -> ClientBuilder { + let (codec_is_json, is_compress) = ClientConfig::get_codec_and_compress(); ClientBuilder { timeout: None, connector: "", directory: None, direct: false, host: "".to_string(), + codec_is_json, + is_compress, } } pub fn from_static(host: &str) -> ClientBuilder { + let (codec_is_json, is_compress) = ClientConfig::get_codec_and_compress(); Self { timeout: None, connector: "", directory: Some(Box::new(StaticDirectory::new(&host))), direct: true, host: host.to_string(), + codec_is_json, + is_compress, } } diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index a81ebfcb..c77a491d 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -20,7 +20,6 @@ use std::str::FromStr; use futures_util::{future, stream, StreamExt, TryStreamExt}; use aws_smithy_http::body::SdkBody; -use dubbo_config::consumer::ConsumerConfig; use http::HeaderValue; use prost::Message; use serde::{Deserialize, Serialize}; @@ -29,7 +28,7 @@ use super::builder::ClientBuilder; use crate::codegen::{ProstCodec, RpcInvocation, SerdeCodec}; use crate::{ - invocation::{IntoStreamingRequest, Invocation, Metadata, Request, Response}, + invocation::{IntoStreamingRequest, Metadata, Request, Response}, protocol::BoxInvoker, status::Status, triple::{ @@ -156,11 +155,9 @@ impl TripleClient { M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let config = - ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); - let (is_json, is_compression) = match config { + let (is_json, is_compression) = match &self.builder { None => (false, true), - Some(config) => (config.codec.clone() == "json".to_string(), config.compress), + Some(builder) => (builder.codec_is_json.clone(), builder.is_compress.clone()), }; let compression = match is_compression { true => self.send_compression_encoding, @@ -231,11 +228,9 @@ impl TripleClient { M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let config = - ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); - let (is_json, is_compression) = match config { + let (is_json, is_compression) = match &self.builder { None => (false, true), - Some(config) => (config.codec.clone() == "json".to_string(), config.compress), + Some(builder) => (builder.codec_is_json.clone(), builder.is_compress.clone()), }; let compression = match is_compression { true => self.send_compression_encoding, @@ -288,11 +283,9 @@ impl TripleClient { M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let config = - ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); - let (is_json, is_compression) = match config { + let (is_json, is_compression) = match &self.builder { None => (false, true), - Some(config) => (config.codec.clone() == "json".to_string(), config.compress), + Some(builder) => (builder.codec_is_json.clone(), builder.is_compress.clone()), }; let compression = match is_compression { true => self.send_compression_encoding, @@ -362,11 +355,9 @@ impl TripleClient { M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let config = - ConsumerConfig::get_global_consumer_config(invocation.get_target_service_unique_name()); - let (is_json, is_compression) = match config { + let (is_json, is_compression) = match &self.builder { None => (false, true), - Some(config) => (config.codec.clone() == "json".to_string(), config.compress), + Some(builder) => (builder.codec_is_json.clone(), builder.is_compress.clone()), }; let compression = match is_compression { true => self.send_compression_encoding, diff --git a/dubbo/src/triple/server/triple.rs b/dubbo/src/triple/server/triple.rs index e6d92fc0..2586e643 100644 --- a/dubbo/src/triple/server/triple.rs +++ b/dubbo/src/triple/server/triple.rs @@ -40,12 +40,12 @@ use dubbo_config::BusinessConfig; pub const GRPC_ACCEPT_ENCODING: &str = "grpc-accept-encoding"; pub const GRPC_ENCODING: &str = "grpc-encoding"; -pub struct TripleServer { - _pd: PhantomData<(T, V)>, +pub struct TripleServer { + _pd: PhantomData<(M1, M2)>, compression: Option, } -impl TripleServer { +impl TripleServer { pub fn new() -> Self { Self { _pd: PhantomData, @@ -54,10 +54,10 @@ impl TripleServer { } } -impl TripleServer +impl TripleServer where - T: Message + for<'a> Deserialize<'a> + Default + 'static, - V: Message + Serialize + Default + 'static, + M1: Message + for<'a> Deserialize<'a> + Default + 'static, + M2: Message + Serialize + Default + 'static, { pub async fn client_streaming( &mut self, @@ -65,7 +65,7 @@ where req: http::Request, ) -> http::Response where - S: ClientStreamingSvc, + S: ClientStreamingSvc, B: Body + Send + 'static, B::Error: Into + Send, { @@ -76,8 +76,8 @@ where .unwrap_or(HeaderValue::from_str("application/json").unwrap()); let is_json = content_type == "application/json" || content_type == "application/grpc+json"; let (decoder, encoder): ( - Box + Send + 'static>, - Box + Send + 'static>, + Box + Send + 'static>, + Box + Send + 'static>, ) = get_codec(is_json); let mut accept_encoding = CompressionEncoding::from_accept_encoding(req.headers()); if self.compression.is_none() || accept_encoding.is_none() { @@ -124,7 +124,7 @@ where req: http::Request, ) -> http::Response where - S: StreamingSvc, + S: StreamingSvc, S::ResponseStream: Send + 'static, B: Body + Send + 'static, B::Error: Into + Send, @@ -137,8 +137,8 @@ where let is_json = content_type == "application/json" || content_type == "application/grpc+json"; let (decoder, encoder): ( - Box + Send + 'static>, - Box + Send + 'static>, + Box + Send + 'static>, + Box + Send + 'static>, ) = get_codec(is_json); // Firstly, get grpc_accept_encoding from http_header, get compression // Secondly, if server enable compression and compression is valid, this method should compress response @@ -181,7 +181,7 @@ where req: http::Request, ) -> http::Response where - S: ServerStreamingSvc, + S: ServerStreamingSvc, S::ResponseStream: Send + 'static, B: Body + Send + 'static, B::Error: Into + Send, @@ -194,8 +194,8 @@ where let is_json = content_type == "application/json" || content_type == "application/grpc+json"; let (decoder, encoder): ( - Box + Send + 'static>, - Box + Send + 'static>, + Box + Send + 'static>, + Box + Send + 'static>, ) = get_codec(is_json); // Firstly, get grpc_accept_encoding from http_header, get compression // Secondly, if server enable compression and compression is valid, this method should compress response @@ -245,7 +245,7 @@ where req: http::Request, ) -> http::Response where - S: UnarySvc, + S: UnarySvc, B: Body + Send + 'static, B::Error: Into + Send, { @@ -266,8 +266,8 @@ where let is_json = content_type == "application/json" || content_type == "application/grpc+json"; let (decoder, encoder): ( - Box + Send + 'static>, - Box + Send + 'static>, + Box + Send + 'static>, + Box + Send + 'static>, ) = get_codec(is_json); let req_stream = req.map(|body| Decoding::new(body, decoder, compression, is_json)); let (parts, mut body) = Request::from_http(req_stream).into_parts(); @@ -328,7 +328,7 @@ where } } -impl BusinessConfig for TripleServer { +impl BusinessConfig for TripleServer { fn init() -> Self { todo!() } From 3c70c89e03b8f384cce5826ebd310cfceb22ef42 Mon Sep 17 00:00:00 2001 From: urara <271014355@qq.com> Date: Fri, 18 Aug 2023 05:10:09 -0400 Subject: [PATCH 11/11] perf: Removed configuration using serialization methods.(#145) The RPC client now exclusively uses protobuf for serialization. --- application.yaml | 3 - config/src/client.rs | 38 --------- config/src/config.rs | 6 +- config/src/lib.rs | 1 - dubbo/src/triple/client/builder.rs | 9 -- dubbo/src/triple/client/triple.rs | 129 +++++++++++++---------------- 6 files changed, 60 insertions(+), 126 deletions(-) delete mode 100644 config/src/client.rs diff --git a/application.yaml b/application.yaml index 2f93a2d1..d357db14 100644 --- a/application.yaml +++ b/application.yaml @@ -17,9 +17,6 @@ dubbo: group: test protocol: triple interface: org.apache.dubbo.sample.tri.Greeter - client: - codec: proto - compress: true consumer: references: GreeterClientImpl: diff --git a/config/src/client.rs b/config/src/client.rs deleted file mode 100644 index 08a00f1f..00000000 --- a/config/src/client.rs +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::get_global_config; -use serde::{Deserialize, Serialize}; - -#[derive(Default, Debug, Clone, Serialize, Deserialize)] -pub struct ClientConfig { - pub codec: String, - pub compress: bool, -} - -impl ClientConfig { - pub fn get_codec_and_compress() -> (bool, bool) { - let config = get_global_config().client.clone(); - match config { - None => (false, true), - Some(cfg) => ( - cfg.codec == "json".to_string().clone(), - cfg.compress.clone(), - ), - } - } -} diff --git a/config/src/config.rs b/config/src/config.rs index 4eb076d2..646873d1 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -17,7 +17,7 @@ use std::{collections::HashMap, env, path::PathBuf}; -use crate::{client::ClientConfig, protocol::Protocol, registry::RegistryConfig}; +use crate::{protocol::Protocol, registry::RegistryConfig}; use dubbo_logger::tracing; use dubbo_utils::yaml_util::yaml_file_parser; use once_cell::sync::OnceCell; @@ -44,9 +44,6 @@ pub struct RootConfig { #[serde(default)] pub registries: HashMap, - #[serde(default)] - pub client: Option, - #[serde(default)] pub data: HashMap, } @@ -66,7 +63,6 @@ impl RootConfig { protocols: HashMap::new(), registries: HashMap::new(), provider: ProviderConfig::new(), - client: None, data: HashMap::new(), } } diff --git a/config/src/lib.rs b/config/src/lib.rs index adfe307a..0748c667 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -17,7 +17,6 @@ pub use config::*; -pub mod client; pub mod config; pub mod protocol; pub mod provider; diff --git a/dubbo/src/triple/client/builder.rs b/dubbo/src/triple/client/builder.rs index a3c3c97c..9dae0f93 100644 --- a/dubbo/src/triple/client/builder.rs +++ b/dubbo/src/triple/client/builder.rs @@ -27,7 +27,6 @@ use crate::{ use aws_smithy_http::body::SdkBody; use dubbo_base::Url; -use dubbo_config::client::ClientConfig; use super::TripleClient; @@ -41,34 +40,26 @@ pub struct ClientBuilder { directory: Option>, pub direct: bool, host: String, - pub codec_is_json: bool, - pub is_compress: bool, } impl ClientBuilder { pub fn new() -> ClientBuilder { - let (codec_is_json, is_compress) = ClientConfig::get_codec_and_compress(); ClientBuilder { timeout: None, connector: "", directory: None, direct: false, host: "".to_string(), - codec_is_json, - is_compress, } } pub fn from_static(host: &str) -> ClientBuilder { - let (codec_is_json, is_compress) = ClientConfig::get_codec_and_compress(); Self { timeout: None, connector: "", directory: Some(Box::new(StaticDirectory::new(&host))), direct: true, host: host.to_string(), - codec_is_json, - is_compress, } } diff --git a/dubbo/src/triple/client/triple.rs b/dubbo/src/triple/client/triple.rs index c77a491d..f8e1175c 100644 --- a/dubbo/src/triple/client/triple.rs +++ b/dubbo/src/triple/client/triple.rs @@ -66,8 +66,6 @@ impl TripleClient { uri: http::Uri, path: http::uri::PathAndQuery, body: SdkBody, - is_json: bool, - compression: bool, ) -> http::Request { let mut parts = uri.into_parts(); parts.path_and_query = Some(path); @@ -93,18 +91,10 @@ impl TripleClient { "authority", HeaderValue::from_str(uri.authority().unwrap().as_str()).unwrap(), ); - if is_json { - req.headers_mut().insert( - "content-type", - HeaderValue::from_static("application/grpc+json"), - ); - } else { - req.headers_mut().insert( - "content-type", - HeaderValue::from_static("application/grpc+proto"), - ); - } - + req.headers_mut().insert( + "content-type", + HeaderValue::from_static("application/grpc+proto"), + ); req.headers_mut() .insert("user-agent", HeaderValue::from_static("dubbo-rust/0.1.0")); req.headers_mut() @@ -119,17 +109,14 @@ impl TripleClient { "tri-unit-info", HeaderValue::from_static("dubbo-rust/0.1.0"), ); - if compression { - if let Some(_encoding) = self.send_compression_encoding { - req.headers_mut() - .insert("grpc-encoding", http::HeaderValue::from_static("gzip")); - req.headers_mut().insert( - "grpc-accept-encoding", - http::HeaderValue::from_static("gzip"), - ); - } + if let Some(_encoding) = self.send_compression_encoding { + req.headers_mut() + .insert("grpc-encoding", http::HeaderValue::from_static("gzip")); + req.headers_mut().insert( + "grpc-accept-encoding", + http::HeaderValue::from_static("gzip"), + ); } - // const ( // TripleContentType = "application/grpc+proto" // TripleUserAgent = "grpc-go/1.35.0-dev" @@ -155,21 +142,19 @@ impl TripleClient { M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let (is_json, is_compression) = match &self.builder { - None => (false, true), - Some(builder) => (builder.codec_is_json.clone(), builder.is_compress.clone()), - }; - let compression = match is_compression { - true => self.send_compression_encoding, - false => None, - }; + let is_json = false; let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, ) = get_codec(is_json); let req = req.map(|m| stream::once(future::ready(m))); - let body_stream = - encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); + let body_stream = encode( + encoder, + req.into_inner().map(Ok), + self.send_compression_encoding, + is_json, + ) + .into_stream(); let body = hyper::Body::wrap_stream(body_stream); let bytes = hyper::body::to_bytes(body).await.unwrap(); let sdk_body = SdkBody::from(bytes); @@ -185,7 +170,7 @@ impl TripleClient { }; let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, is_json, is_compression); + let req = self.map_request(http_uri.clone(), path, sdk_body); let response = conn .call(req) @@ -194,7 +179,9 @@ impl TripleClient { match response { Ok(v) => { - let resp = v.map(|body| Decoding::new(body, decoder, compression, is_json)); + let resp = v.map(|body| { + Decoding::new(body, decoder, self.send_compression_encoding, is_json) + }); let (mut parts, body) = Response::from_http(resp).into_parts(); futures_util::pin_mut!(body); @@ -228,20 +215,19 @@ impl TripleClient { M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let (is_json, is_compression) = match &self.builder { - None => (false, true), - Some(builder) => (builder.codec_is_json.clone(), builder.is_compress.clone()), - }; - let compression = match is_compression { - true => self.send_compression_encoding, - false => None, - }; + let is_json = false; let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, ) = get_codec(is_json); let req = req.into_streaming_request(); - let en = encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); + let en = encode( + encoder, + req.into_inner().map(Ok), + self.send_compression_encoding, + is_json, + ) + .into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); @@ -256,7 +242,7 @@ impl TripleClient { }; let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, is_json, is_compression); + let req = self.map_request(http_uri.clone(), path, sdk_body); let response = conn .call(req) @@ -265,7 +251,9 @@ impl TripleClient { match response { Ok(v) => { - let resp = v.map(|body| Decoding::new(body, decoder, compression, is_json)); + let resp = v.map(|body| { + Decoding::new(body, decoder, self.send_compression_encoding, is_json) + }); Ok(Response::from_http(resp)) } @@ -283,20 +271,19 @@ impl TripleClient { M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let (is_json, is_compression) = match &self.builder { - None => (false, true), - Some(builder) => (builder.codec_is_json.clone(), builder.is_compress.clone()), - }; - let compression = match is_compression { - true => self.send_compression_encoding, - false => None, - }; + let is_json = false; let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, ) = get_codec(is_json); let req = req.into_streaming_request(); - let en = encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); + let en = encode( + encoder, + req.into_inner().map(Ok), + self.send_compression_encoding, + is_json, + ) + .into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); @@ -311,7 +298,7 @@ impl TripleClient { }; let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, is_json, is_compression); + let req = self.map_request(http_uri.clone(), path, sdk_body); // let mut conn = Connection::new().with_host(http_uri); let response = conn @@ -321,7 +308,9 @@ impl TripleClient { match response { Ok(v) => { - let resp = v.map(|body| Decoding::new(body, decoder, compression, is_json)); + let resp = v.map(|body| { + Decoding::new(body, decoder, self.send_compression_encoding, is_json) + }); let (mut parts, body) = Response::from_http(resp).into_parts(); futures_util::pin_mut!(body); @@ -355,21 +344,19 @@ impl TripleClient { M1: Message + Send + Sync + 'static + Serialize, M2: Message + Send + Sync + 'static + for<'a> Deserialize<'a> + Default, { - let (is_json, is_compression) = match &self.builder { - None => (false, true), - Some(builder) => (builder.codec_is_json.clone(), builder.is_compress.clone()), - }; - let compression = match is_compression { - true => self.send_compression_encoding, - false => None, - }; - + let is_json = false; let (decoder, encoder): ( Box + Send + 'static>, Box + Send + 'static>, ) = get_codec(is_json); let req = req.map(|m| stream::once(future::ready(m))); - let en = encode(encoder, req.into_inner().map(Ok), compression, is_json).into_stream(); + let en = encode( + encoder, + req.into_inner().map(Ok), + self.send_compression_encoding, + is_json, + ) + .into_stream(); let body = hyper::Body::wrap_stream(en); let sdk_body = SdkBody::from(body); @@ -383,7 +370,7 @@ impl TripleClient { .unwrap(), }; let http_uri = http::Uri::from_str(&conn.get_url().to_url()).unwrap(); - let req = self.map_request(http_uri.clone(), path, sdk_body, is_json, is_compression); + let req = self.map_request(http_uri.clone(), path, sdk_body); let response = conn .call(req) @@ -392,7 +379,9 @@ impl TripleClient { match response { Ok(v) => { - let resp = v.map(|body| Decoding::new(body, decoder, compression, is_json)); + let resp = v.map(|body| { + Decoding::new(body, decoder, self.send_compression_encoding, is_json) + }); Ok(Response::from_http(resp)) }