From 883d39d39b04e2ef24ac08d3103a760a55f36110 Mon Sep 17 00:00:00 2001 From: hubertshelley Date: Sun, 16 Jun 2024 10:05:58 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/candle_whisper/Cargo.toml | 4 ++-- examples/custom_tokio_listener/Cargo.toml | 2 +- examples/custom_tokio_runtime/Cargo.toml | 2 +- examples/exception_handler/Cargo.toml | 2 +- examples/form/Cargo.toml | 2 +- examples/grpc/Cargo.toml | 9 ++++----- examples/grpc_h2c/Cargo.toml | 9 ++++----- examples/grpc_streaming/Cargo.toml | 9 ++++----- examples/multipart-form/Cargo.toml | 2 +- examples/sse-chat/Cargo.toml | 2 +- examples/templates/Cargo.toml | 2 +- examples/todo/Cargo.toml | 2 +- examples/websocket-chat/Cargo.toml | 2 +- examples/websocket/Cargo.toml | 6 +++--- silent/Cargo.toml | 14 +++++++------- 15 files changed, 33 insertions(+), 36 deletions(-) diff --git a/examples/candle_whisper/Cargo.toml b/examples/candle_whisper/Cargo.toml index d38267a..1c7ecf1 100644 --- a/examples/candle_whisper/Cargo.toml +++ b/examples/candle_whisper/Cargo.toml @@ -21,12 +21,12 @@ bindgen_cuda = { version = "0.1.5", optional = true } [dependencies] -clap = { version = "4.5.4", features = ["derive"] } +clap = { version = "4.5.7", features = ["derive"] } serde = { version = "1.0", features = ["derive"] } silent = { path = "../../silent", features = ["multipart"] } symphonia = { version = "0.5.4", features = ["all"] } anyhow = "1.0.86" -tokio = { version = "1.37.0", features = ["full"] } +tokio = { version = "1.38.0", features = ["full"] } #candle-core = { version = "0.3.2" } #candle-nn = { version = "0.3.2" } diff --git a/examples/custom_tokio_listener/Cargo.toml b/examples/custom_tokio_listener/Cargo.toml index b2df581..58527bc 100644 --- a/examples/custom_tokio_listener/Cargo.toml +++ b/examples/custom_tokio_listener/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } async-trait = "0.1.80" -tokio = { version = "1.37.0", features = ["full"] } +tokio = { version = "1.38.0", features = ["full"] } diff --git a/examples/custom_tokio_runtime/Cargo.toml b/examples/custom_tokio_runtime/Cargo.toml index 87f32a2..58c97d0 100644 --- a/examples/custom_tokio_runtime/Cargo.toml +++ b/examples/custom_tokio_runtime/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } async-trait = "0.1.80" -tokio = { version = "1.37.0", features = ["full"] } +tokio = { version = "1.38.0", features = ["full"] } diff --git a/examples/exception_handler/Cargo.toml b/examples/exception_handler/Cargo.toml index 6d0fa02..41ee57b 100644 --- a/examples/exception_handler/Cargo.toml +++ b/examples/exception_handler/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } diff --git a/examples/form/Cargo.toml b/examples/form/Cargo.toml index 8d78a04..7938132 100644 --- a/examples/form/Cargo.toml +++ b/examples/form/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } diff --git a/examples/grpc/Cargo.toml b/examples/grpc/Cargo.toml index c283f6d..dffc3d0 100644 --- a/examples/grpc/Cargo.toml +++ b/examples/grpc/Cargo.toml @@ -13,20 +13,19 @@ name = "example-grpc-client" path = "src/client.rs" [dependencies] -tonic = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } -tonic-reflection = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } +tonic = { git = "https://github.com/hyperium/tonic" } prost = "0.12" -tokio = { version = "1.37", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.38", features = ["macros", "rt-multi-thread"] } silent = { path = "../../silent", features = ["grpc"] } axum = "0.7" async-trait = "0.1.80" hyper = "1.3.1" -hyper-util = "0.1.3" +hyper-util = "0.1.5" bytes = "1.6.0" pin-project-lite = "0.2.14" http-body = "1.0.0" http = "1.1.0" -http-body-util = "0.1.1" +http-body-util = "0.1.2" [build-dependencies] tonic-build = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } diff --git a/examples/grpc_h2c/Cargo.toml b/examples/grpc_h2c/Cargo.toml index ee0afb3..d906359 100644 --- a/examples/grpc_h2c/Cargo.toml +++ b/examples/grpc_h2c/Cargo.toml @@ -13,20 +13,19 @@ name = "example-grpc-client" path = "src/client.rs" [dependencies] -tonic = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } -tonic-reflection = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } +tonic = { git = "https://github.com/hyperium/tonic" } prost = "0.12" -tokio = { version = "1.37", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.38", features = ["macros", "rt-multi-thread"] } silent = { path = "../../silent", features = ["grpc"] } axum = "0.7" async-trait = "0.1.80" hyper = "1.3.1" -hyper-util = "0.1.3" +hyper-util = "0.1.5" bytes = "1.6.0" pin-project-lite = "0.2.14" http-body = "1.0.0" http = "1.1.0" -http-body-util = "0.1.1" +http-body-util = "0.1.2" tower = "0.4.13" [build-dependencies] diff --git a/examples/grpc_streaming/Cargo.toml b/examples/grpc_streaming/Cargo.toml index ba9d33c..e1410b6 100644 --- a/examples/grpc_streaming/Cargo.toml +++ b/examples/grpc_streaming/Cargo.toml @@ -13,20 +13,19 @@ name = "example-grpc-client" path = "src/client.rs" [dependencies] -tonic = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } -tonic-reflection = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } +tonic = { git = "https://github.com/hyperium/tonic" } prost = "0.12" -tokio = { version = "1.37", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.38", features = ["macros", "rt-multi-thread"] } silent = { path = "../../silent", features = ["grpc"] } axum = "0.7" async-trait = "0.1.80" hyper = "1.3.1" -hyper-util = "0.1.3" +hyper-util = "0.1.5" bytes = "1.6.0" pin-project-lite = "0.2.14" http-body = "1.0.0" http = "1.1.0" -http-body-util = "0.1.1" +http-body-util = "0.1.2" tokio-stream = "0.1.15" h2 = "0.4.5" diff --git a/examples/multipart-form/Cargo.toml b/examples/multipart-form/Cargo.toml index 6bd82c1..9d36b9e 100644 --- a/examples/multipart-form/Cargo.toml +++ b/examples/multipart-form/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] silent = { path = "../../silent", features = ["multipart"] } -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } diff --git a/examples/sse-chat/Cargo.toml b/examples/sse-chat/Cargo.toml index 3ae28d9..ac0b336 100644 --- a/examples/sse-chat/Cargo.toml +++ b/examples/sse-chat/Cargo.toml @@ -11,4 +11,4 @@ once_cell = "1" parking_lot = "0.12" tokio = { version = "1", features = ["macros"] } tokio-stream = { version = "0.1", features = ["net"] } -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } diff --git a/examples/templates/Cargo.toml b/examples/templates/Cargo.toml index 8889daa..75350c9 100644 --- a/examples/templates/Cargo.toml +++ b/examples/templates/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } silent = { path = "../../silent", features = ["template"] } diff --git a/examples/todo/Cargo.toml b/examples/todo/Cargo.toml index 864ebed..cdff445 100644 --- a/examples/todo/Cargo.toml +++ b/examples/todo/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } uuid = { version = "1.8.0", features = ["serde", "v4"] } async-trait = "0.1.80" diff --git a/examples/websocket-chat/Cargo.toml b/examples/websocket-chat/Cargo.toml index 140ea86..2eb2460 100644 --- a/examples/websocket-chat/Cargo.toml +++ b/examples/websocket-chat/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] silent = { path = "../../silent", features = ["upgrade"] } -tokio = { version = "1.37.0", features = ["full"] } +tokio = { version = "1.38.0", features = ["full"] } tokio-stream = { version = "0.1.15", features = ["net"] } futures-util = { version = "0.3.30", default-features = false } once_cell = "1.19.0" diff --git a/examples/websocket/Cargo.toml b/examples/websocket/Cargo.toml index 2f66a48..9a6fec1 100644 --- a/examples/websocket/Cargo.toml +++ b/examples/websocket/Cargo.toml @@ -8,8 +8,8 @@ edition = "2021" [dependencies] async-trait = "0.1.80" silent = { path = "../../silent", features = ["upgrade"] } -tokio = { version = "1.37.0", features = ["full"] } -tokio-tungstenite = "0.21.0" +tokio = { version = "1.38.0", features = ["full"] } +tokio-tungstenite = "0.23.0" futures-util = "0.3.30" -backtrace = "0.3.71" +backtrace = "0.3.73" headers = "0.4.0" diff --git a/silent/Cargo.toml b/silent/Cargo.toml index 7f3a3c0..68cd221 100644 --- a/silent/Cargo.toml +++ b/silent/Cargo.toml @@ -36,22 +36,22 @@ grpc = ["upgrade", "dep:axum", "dep:tower-service", "dep:pin-project-lite", "dep # Basic dependencies thiserror = "1.0.61" hyper = { version = "1.3.1", features = ["full"] } -hyper-util = { version = "0.1.3", features = ["server-auto", "tokio"] } -tokio = { version = "1.37.0", optional = true } +hyper-util = { version = "0.1.5", features = ["server-auto", "tokio"] } +tokio = { version = "1.38.0", optional = true } bytes = "1.6.0" -http-body-util = "0.1.1" +http-body-util = "0.1.2" tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["local-time"] } async-trait = "0.1.80" -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } serde_json = "1.0.117" uuid = "1.8.0" -url = "2.5.0" +url = "2.5.1" serde_urlencoded = "0.7.1" mime = "0.3.17" futures-util = "0.3.30" chrono = { version = "0.4.38", default-features = false, features = ["clock"] } -tokio-tungstenite = { version = "0.21.0", optional = true } +tokio-tungstenite = { version = "0.23.0", optional = true } headers = "0.4.0" tokio-stream = { version = "0.1.15", features = ["net"], optional = true } pin-project = { version = "1.1", optional = true } @@ -73,7 +73,7 @@ textnonce = { version = "1.0.0", optional = true } # Template -tera = { version = "1.19.1", optional = true } +tera = { version = "1.20.0", optional = true } # Session async-session = { version = "3.0.0", optional = true } From e92cbe2df20bd9874f1681c1df57e7f673aa8a1e Mon Sep 17 00:00:00 2001 From: hubertshelley Date: Sun, 16 Jun 2024 16:12:51 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E5=B7=B2=E5=AE=8C=E6=88=90=EF=BC=8C=E5=BE=85tonic=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/grpc/Cargo.toml | 8 --- examples/grpc/src/main.rs | 14 +++-- examples/grpc_h2c/Cargo.toml | 11 +--- examples/grpc_h2c/src/main.rs | 7 +-- examples/grpc_streaming/Cargo.toml | 10 +-- examples/grpc_streaming/src/main.rs | 22 +++---- silent/Cargo.toml | 5 +- silent/src/grpc/handler.rs | 96 ++++++++++++++++++++++++----- silent/src/grpc/service.rs | 59 ++++++++++++++---- silent/src/grpc/utils.rs | 5 +- silent/src/route/handler_match.rs | 29 ++++++--- silent/src/route/root.rs | 69 ++++++++++----------- 12 files changed, 207 insertions(+), 128 deletions(-) diff --git a/examples/grpc/Cargo.toml b/examples/grpc/Cargo.toml index dffc3d0..8bd9c4b 100644 --- a/examples/grpc/Cargo.toml +++ b/examples/grpc/Cargo.toml @@ -17,15 +17,7 @@ tonic = { git = "https://github.com/hyperium/tonic" } prost = "0.12" tokio = { version = "1.38", features = ["macros", "rt-multi-thread"] } silent = { path = "../../silent", features = ["grpc"] } -axum = "0.7" async-trait = "0.1.80" -hyper = "1.3.1" -hyper-util = "0.1.5" -bytes = "1.6.0" -pin-project-lite = "0.2.14" -http-body = "1.0.0" -http = "1.1.0" -http-body-util = "0.1.2" [build-dependencies] tonic-build = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } diff --git a/examples/grpc/src/main.rs b/examples/grpc/src/main.rs index 020b55e..d896607 100644 --- a/examples/grpc/src/main.rs +++ b/examples/grpc/src/main.rs @@ -1,8 +1,9 @@ use async_trait::async_trait; +use tonic::{Request, Response, Status}; + use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; use silent::prelude::{logger, HandlerAppend, Level, Route, RouteService, Server}; -use tonic::{transport::Server as TonicServer, Request, Response, Status}; mod client; @@ -35,12 +36,13 @@ async fn main() -> Result<(), Box> { let greeter = MyGreeter::default(); logger::fmt().with_max_level(Level::INFO).init(); let greeter_server = GreeterServer::new(greeter); - let grpc = TonicServer::builder() - // Wrap all services in the middleware stack - .add_service(greeter_server) - .into_router(); + // let grpc = TonicServer::builder() + // // Wrap all services in the middleware stack + // .add_service(greeter_server) + // .into_router(); let route = Route::new("").get(|_req| async { Ok("hello world") }); - let root = route.route().with_grpc(grpc.into()); + let root = route.route().with_grpc(greeter_server.into()); + println!("route: \n{:?}", root); Server::new() .bind("0.0.0.0:50051".parse().unwrap()) .serve(root) diff --git a/examples/grpc_h2c/Cargo.toml b/examples/grpc_h2c/Cargo.toml index d906359..7cd0f6a 100644 --- a/examples/grpc_h2c/Cargo.toml +++ b/examples/grpc_h2c/Cargo.toml @@ -17,16 +17,7 @@ tonic = { git = "https://github.com/hyperium/tonic" } prost = "0.12" tokio = { version = "1.38", features = ["macros", "rt-multi-thread"] } silent = { path = "../../silent", features = ["grpc"] } -axum = "0.7" async-trait = "0.1.80" -hyper = "1.3.1" -hyper-util = "0.1.5" -bytes = "1.6.0" -pin-project-lite = "0.2.14" -http-body = "1.0.0" -http = "1.1.0" -http-body-util = "0.1.2" -tower = "0.4.13" [build-dependencies] -tonic-build = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } +tonic-build = { git = "https://github.com/hyperium/tonic" } diff --git a/examples/grpc_h2c/src/main.rs b/examples/grpc_h2c/src/main.rs index 19e31fb..f6d1e21 100644 --- a/examples/grpc_h2c/src/main.rs +++ b/examples/grpc_h2c/src/main.rs @@ -1,5 +1,5 @@ // use tonic::transport::server::TowerToHyperService; -use tonic::{transport::Server, Request, Response, Status}; +use tonic::{Request, Response, Status}; use hello_world::greeter_server::{Greeter, GreeterServer}; use hello_world::{HelloReply, HelloRequest}; @@ -32,11 +32,8 @@ async fn main() -> Result<(), Box> { let greeter = MyGreeter::default(); logger::fmt().with_max_level(Level::INFO).init(); - let grpc = Server::builder() - .add_service(GreeterServer::new(greeter)) - .into_router(); let route = Route::new("").get(|_req| async { Ok("hello world") }); - let root = route.route().with_grpc(grpc.into()); + let root = route.route().with_grpc(GreeterServer::new(greeter).into()); silent::prelude::Server::new() .bind("0.0.0.0:50051".parse().unwrap()) .serve(root) diff --git a/examples/grpc_streaming/Cargo.toml b/examples/grpc_streaming/Cargo.toml index e1410b6..9922214 100644 --- a/examples/grpc_streaming/Cargo.toml +++ b/examples/grpc_streaming/Cargo.toml @@ -17,17 +17,9 @@ tonic = { git = "https://github.com/hyperium/tonic" } prost = "0.12" tokio = { version = "1.38", features = ["macros", "rt-multi-thread"] } silent = { path = "../../silent", features = ["grpc"] } -axum = "0.7" async-trait = "0.1.80" -hyper = "1.3.1" -hyper-util = "0.1.5" -bytes = "1.6.0" -pin-project-lite = "0.2.14" -http-body = "1.0.0" -http = "1.1.0" -http-body-util = "0.1.2" tokio-stream = "0.1.15" h2 = "0.4.5" [build-dependencies] -tonic-build = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } +tonic-build = { git = "https://github.com/hyperium/tonic" } diff --git a/examples/grpc_streaming/src/main.rs b/examples/grpc_streaming/src/main.rs index f649f6b..b442260 100644 --- a/examples/grpc_streaming/src/main.rs +++ b/examples/grpc_streaming/src/main.rs @@ -1,3 +1,10 @@ +use std::{error::Error, io::ErrorKind, pin::Pin, time::Duration}; + +use tokio::sync::mpsc; +use tokio_stream::{wrappers::ReceiverStream, Stream, StreamExt}; +use tonic::{Request, Response, Status, Streaming}; + +use pb::{EchoRequest, EchoResponse}; use silent::prelude::{logger, HandlerAppend, Level, Route, RouteService, Server}; mod client; @@ -6,13 +13,6 @@ pub mod pb { tonic::include_proto!("grpc.examples.echo"); } -use std::{error::Error, io::ErrorKind, pin::Pin, time::Duration}; -use tokio::sync::mpsc; -use tokio_stream::{wrappers::ReceiverStream, Stream, StreamExt}; -use tonic::{transport::Server as TonicServer, Request, Response, Status, Streaming}; - -use pb::{EchoRequest, EchoResponse}; - type EchoResult = Result, Status>; type ResponseStream = Pin> + Send>>; @@ -149,12 +149,10 @@ impl pb::echo_server::Echo for EchoServer { async fn main() -> Result<(), Box> { logger::fmt().with_max_level(Level::INFO).init(); let server = EchoServer {}; - let grpc = TonicServer::builder() - // Wrap all services in the middleware stack - .add_service(pb::echo_server::EchoServer::new(server)) - .into_router(); let route = Route::new("").get(|_req| async { Ok("hello world") }); - let root = route.route().with_grpc(grpc.into()); + let root = route + .route() + .with_grpc(pb::echo_server::EchoServer::new(server).into()); Server::new() .bind("0.0.0.0:50051".parse().unwrap()) .serve(root) diff --git a/silent/Cargo.toml b/silent/Cargo.toml index 68cd221..2a7538e 100644 --- a/silent/Cargo.toml +++ b/silent/Cargo.toml @@ -30,7 +30,7 @@ template = ["dep:tera"] #wasi = ["tokio/sync"] test = ["tokio/macros", "tokio/rt"] scheduler = ["dep:cron"] -grpc = ["upgrade", "dep:axum", "dep:tower-service", "dep:pin-project-lite", "dep:pin-project", "dep:tokio-stream"] +grpc = ["upgrade", "dep:tonic", "dep:pin-project-lite", "dep:pin-project", "dep:tokio-stream"] [dependencies] # Basic dependencies @@ -80,8 +80,7 @@ async-session = { version = "3.0.0", optional = true } cookie = { version = "0.18.1", features = ["secure", "percent-encode"], optional = true } # Grpc -axum = { version = "0.7.5", optional = true } -tower-service = { version = "0.3.2", optional = true } +tonic = { git = "https://github.com/hyperium/tonic", optional = true } # Security argon2 = { version = "0.5.3", optional = true } diff --git a/silent/src/grpc/handler.rs b/silent/src/grpc/handler.rs index 14ee187..5ed727d 100644 --- a/silent/src/grpc/handler.rs +++ b/silent/src/grpc/handler.rs @@ -1,27 +1,88 @@ -use super::utils::merge_axum; -use crate::grpc::service::GrpcService; -use crate::{Handler, Response, SilentError}; +use std::sync::Arc; + use async_trait::async_trait; use http::{header, HeaderValue, StatusCode}; +use http_body_util::BodyExt; use hyper::upgrade::OnUpgrade; use hyper_util::rt::TokioExecutor; -use tower_service::Service; -use tracing::error; +use tokio::sync::Mutex; +use tonic::body::BoxBody; +use tonic::codegen::Service; +use tonic::server::NamedService; +use tonic::Status; + +use crate::grpc::service::GrpcService; +use crate::{Handler, Response, SilentError}; + +use super::utils::merge_grpc_response; + +trait GrpcRequestAdapter { + fn into_grpc_request(self) -> http::Request; +} + +impl GrpcRequestAdapter for crate::Request { + fn into_grpc_request(self) -> http::Request { + let (parts, body) = self.into_http().into_parts(); + http::Request::from_parts( + parts, + body.map_err(|e| { + Status::internal(format!("convert request to http request failed: {}", e)) + }) + .boxed_unsync(), + ) + } +} #[derive(Clone)] -pub struct GrpcHandler(axum::Router<()>); +pub struct GrpcHandler { + inner: Arc>, +} -impl From> for GrpcHandler { - fn from(router: axum::Router<()>) -> Self { - Self(router) +impl GrpcHandler +where + S: Service, Response = http::Response> + NamedService, + S: Clone + Send + 'static, + S: Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into> + Send, +{ + pub fn new(service: S) -> Self { + Self { + inner: Arc::new(Mutex::new(service)), + } + } + pub fn path(&self) -> &str { + S::NAME + } +} + +impl From for GrpcHandler +where + S: Service, Response = http::Response> + NamedService, + S: Clone + Send + 'static, + S: Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into> + Send, +{ + fn from(service: S) -> Self { + Self { + inner: Arc::new(Mutex::new(service)), + } } } #[async_trait] -impl Handler for GrpcHandler { +impl Handler for GrpcHandler +where + S: Service, Response = http::Response>, + S: Clone + Send + 'static, + S: Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into> + Send, +{ async fn call(&self, mut req: crate::Request) -> crate::Result { if let Some(on_upgrade) = req.extensions_mut().remove::() { - let handler = self.0.clone(); + let handler = self.inner.clone(); tokio::spawn(async move { let conn = on_upgrade.await; if conn.is_err() { @@ -45,18 +106,19 @@ impl Handler for GrpcHandler { .insert(header::UPGRADE, HeaderValue::from_static("h2c")); Ok(res) } else { - let mut handler = self.0.clone(); - let req = req.into_http(); + let handler = self.inner.clone(); + let mut handler = handler.lock().await; + let req = req.into_grpc_request(); - let axum_res = handler.call(req).await.map_err(|e| { - error!(error = ?e, "call axum router failed: {}", e); + let grpc_res = handler.call(req).await.map_err(|e| { SilentError::business_error( StatusCode::INTERNAL_SERVER_ERROR, - format!("call axum router failed: {}", e), + format!("grpc call failed: {}", e.into()), ) })?; + println!("{:?}", grpc_res); let mut res = Response::empty(); - merge_axum(&mut res, axum_res).await; + merge_grpc_response(&mut res, grpc_res).await; Ok(res) } diff --git a/silent/src/grpc/service.rs b/silent/src/grpc/service.rs index 9a097a0..71bb18f 100644 --- a/silent/src/grpc/service.rs +++ b/silent/src/grpc/service.rs @@ -1,40 +1,75 @@ use std::future::Future; use std::pin::Pin; +use std::sync::Arc; +use http_body_util::BodyExt; use hyper::body::Incoming; use hyper::service::Service as HyperService; -use tower_service::Service; - -use crate::log::error; +use tokio::sync::Mutex; +use tonic::body::BoxBody; +use tonic::codegen::Service; +use tonic::Status; +use tracing::error; #[doc(hidden)] #[derive(Clone)] -pub struct GrpcService { - pub(crate) handler: axum::Router<()>, +pub struct GrpcService +where + S: Service, Response = http::Response>, + S: Clone + Send + 'static, + S: Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into> + Send, +{ + pub(crate) handler: Arc>, } -impl GrpcService { +impl GrpcService +where + S: Service, Response = http::Response>, + S: Clone + Send + 'static, + S: Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into> + Send, +{ #[inline] #[allow(dead_code)] - pub fn new(handler: axum::Router<()>) -> Self { + pub fn new(handler: Arc>) -> Self { Self { handler } } } -impl HyperService> for GrpcService { - type Response = axum::response::Response; - type Error = hyper::Error; +impl HyperService> for GrpcService +where + S: Service, Response = http::Response>, + S: Clone + Send + 'static, + S: Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into> + Send, +{ + type Response = http::Response; + type Error = S::Error; type Future = Pin> + Send>>; #[inline] fn call(&self, req: hyper::Request) -> Self::Future { - let mut handler = self.handler.clone(); + let (parts, body) = req.into_parts(); + let req = http::Request::from_parts( + parts, + body.map_err(|e| { + Status::internal(format!("convert request to http request failed: {}", e)) + }) + .boxed_unsync(), + ); + let handler = self.handler.clone(); Box::pin(async move { let res = handler + .lock() + .await .call(req) .await .map_err(|e| { - error!(error = ?e, "call grpc router failed: {}", e); + error!("call grpc failed: {:?}", e.into()); }) .unwrap(); Ok(res) diff --git a/silent/src/grpc/utils.rs b/silent/src/grpc/utils.rs index 7711ae1..6a57be1 100644 --- a/silent/src/grpc/utils.rs +++ b/silent/src/grpc/utils.rs @@ -2,12 +2,13 @@ use crate::prelude::ResBody; use crate::Response; use http::response::Parts; use http_body_util::BodyExt; +use tonic::body::BoxBody; #[cfg(feature = "grpc")] /// 合并axum响应 #[inline] -pub async fn merge_axum(res: &mut Response, axum_res: axum::response::Response) { - let (parts, body) = axum_res.into_parts(); +pub async fn merge_grpc_response(res: &mut Response, grpc_res: http::Response) { + let (parts, body) = grpc_res.into_parts(); let Parts { status, headers, diff --git a/silent/src/route/handler_match.rs b/silent/src/route/handler_match.rs index 32e48aa..cb3a452 100644 --- a/silent/src/route/handler_match.rs +++ b/silent/src/route/handler_match.rs @@ -42,7 +42,12 @@ impl<'a> From<&'a str> for SpecialPath { let mut type_str = value.splitn(2, ':'); let key = type_str.next().unwrap_or(""); let path_type = type_str.next().unwrap_or(""); + println!("key: {}, path_type: {}", key, path_type); match path_type { + "**" => SpecialPath::FullPath(key.to_string()), + "*" => SpecialPath::Path(key.to_string()), + "full_path" => SpecialPath::FullPath(key.to_string()), + "path" => SpecialPath::Path(key.to_string()), "str" => SpecialPath::String(key.to_string()), "int" => SpecialPath::Int(key.to_string()), "i64" => SpecialPath::I64(key.to_string()), @@ -50,10 +55,6 @@ impl<'a> From<&'a str> for SpecialPath { "u64" => SpecialPath::U64(key.to_string()), "u32" => SpecialPath::U32(key.to_string()), "uuid" => SpecialPath::UUid(key.to_string()), - "path" => SpecialPath::Path(key.to_string()), - "full_path" => SpecialPath::FullPath(key.to_string()), - "*" => SpecialPath::Path(key.to_string()), - "**" => SpecialPath::FullPath(key.to_string()), _ => SpecialPath::String(key.to_string()), } } @@ -128,13 +129,23 @@ impl Match for Route { self.last_matched(req, last_url) } SpecialPath::FullPath(key) => { + println!("SpecialPath::FullPath: path: {}", path); req.set_path_params(key, PathParam::Path(path.to_string())); match self.last_matched(req, last_url) { - RouteMatched::Matched(route) => RouteMatched::Matched(route), - RouteMatched::Unmatched => match self.handler.is_empty() { - true => RouteMatched::Unmatched, - false => RouteMatched::Matched(self.clone()), - }, + RouteMatched::Matched(route) => { + println!("SpecialPath::FullPath: matched: {}", route.path); + RouteMatched::Matched(route) + } + RouteMatched::Unmatched => { + println!( + "SpecialPath::FullPath: Unmatched matched: {}", + self.handler.len() + ); + match self.handler.is_empty() { + true => RouteMatched::Unmatched, + false => RouteMatched::Matched(self.clone()), + } + } } } } diff --git a/silent/src/route/root.rs b/silent/src/route/root.rs index ef63571..c4331ee 100644 --- a/silent/src/route/root.rs +++ b/silent/src/route/root.rs @@ -1,4 +1,8 @@ use crate::error::{ExceptionHandler, ExceptionHandlerWrapper}; +#[cfg(feature = "grpc")] +use crate::grpc::GrpcHandler; +#[cfg(feature = "grpc")] +use crate::prelude::HandlerGetter; use crate::route::handler_match::{Match, RouteMatched}; use crate::route::Route; #[cfg(feature = "session")] @@ -7,23 +11,22 @@ use crate::session::SessionMiddleware; use crate::templates::TemplateMiddleware; #[cfg(feature = "scheduler")] use crate::Scheduler; -#[cfg(feature = "grpc")] -use crate::{grpc::GrpcHandler, Handler}; use crate::{ Configs, MiddleWareHandler, MiddlewareResult, Request, Response, SilentError, StatusCode, }; #[cfg(feature = "session")] use async_session::{Session, SessionStore}; use chrono::Utc; -use http::{header, HeaderValue}; -use mime::Mime; +use http::Method; use std::fmt; use std::future::Future; use std::net::SocketAddr; -use std::str::FromStr; use std::sync::Arc; #[cfg(feature = "scheduler")] use tokio::sync::Mutex; +use tonic::body::BoxBody; +use tonic::codegen::Service; +use tonic::server::NamedService; #[derive(Clone, Default)] pub struct RootRoute { @@ -35,8 +38,6 @@ pub struct RootRoute { pub(crate) configs: Option, #[cfg(feature = "scheduler")] pub(crate) scheduler: Arc>, - #[cfg(feature = "grpc")] - pub(crate) grpc: Option, } impl fmt::Debug for RootRoute { @@ -62,19 +63,38 @@ impl RootRoute { configs: None, #[cfg(feature = "scheduler")] scheduler: Arc::new(Mutex::new(Scheduler::new())), - #[cfg(feature = "grpc")] - grpc: None, } } #[cfg(feature = "grpc")] - pub fn grpc(&mut self, grpc: GrpcHandler) { - self.grpc = Some(grpc); + pub fn grpc(&mut self, grpc: GrpcHandler) + where + S: Service, Response = http::Response> + NamedService, + S: Clone + Send + 'static, + S: Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into> + Send, + { + let path = grpc.path().to_string(); + let handler = Arc::new(grpc); + let route = Route::new(path.as_str()).append( + Route::new("") + .insert_handler(Method::POST, handler.clone()) + .insert_handler(Method::GET, handler), + ); + self.push(route) } #[cfg(feature = "grpc")] - pub fn with_grpc(mut self, grpc: GrpcHandler) -> Self { - self.grpc = Some(grpc); + pub fn with_grpc(mut self, grpc: GrpcHandler) -> Self + where + S: Service, Response = http::Response> + NamedService, + S: Clone + Send + 'static, + S: Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into> + Send, + { + self.grpc(grpc); self } @@ -134,28 +154,7 @@ impl RootRoute { MiddlewareResult::Error(err) => return Err(err), } } - if req.content_type() == Some(Mime::from_str("application/grpc").unwrap()) - || req.headers().get(header::UPGRADE) == Some(&HeaderValue::from_static("h2c")) - { - #[cfg(feature = "grpc")] - { - return if let Some(grpc) = self.grpc.clone() { - grpc.call(req).await - } else { - Err(SilentError::business_error( - StatusCode::NOT_IMPLEMENTED, - "grpc handler not set".to_string(), - )) - }; - } - #[cfg(not(feature = "grpc"))] - { - return Err(SilentError::business_error( - StatusCode::NOT_IMPLEMENTED, - "grpc not enabled".to_string(), - )); - } - } + println!("path: {}", path); match self.handler_match(&mut req, path.as_str()) { RouteMatched::Matched(route) => match route.handler.get(req.method()) { None => { From 9029147b4dada5add0ae097041424fce0c21993f Mon Sep 17 00:00:00 2001 From: hubertshelley Date: Tue, 9 Jul 2024 09:31:02 +0800 Subject: [PATCH 3/3] =?UTF-8?q?perf:=20grpc=E5=8F=AF=E7=94=A8=E8=B0=83?= =?UTF-8?q?=E6=95=B4=EF=BC=8C=E5=8E=BB=E9=99=A4tower,=20axum=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/candle_whisper/Cargo.toml | 4 ++-- examples/configs/Cargo.toml | 2 +- examples/custom_handler/Cargo.toml | 2 +- examples/custom_tokio_listener/Cargo.toml | 2 +- examples/custom_tokio_runtime/Cargo.toml | 2 +- examples/exception_handler/Cargo.toml | 2 +- examples/form/Cargo.toml | 2 +- examples/grpc/Cargo.toml | 8 ++++---- examples/grpc_h2c/Cargo.toml | 8 ++++---- examples/grpc_streaming/Cargo.toml | 8 ++++---- examples/middleware/Cargo.toml | 2 +- examples/multipart-form/Cargo.toml | 2 +- examples/sse-chat/Cargo.toml | 2 +- examples/templates/Cargo.toml | 2 +- examples/todo/Cargo.toml | 6 +++--- examples/websocket/Cargo.toml | 4 ++-- silent/Cargo.toml | 20 ++++++++++---------- 17 files changed, 39 insertions(+), 39 deletions(-) diff --git a/examples/candle_whisper/Cargo.toml b/examples/candle_whisper/Cargo.toml index 1c7ecf1..e871cfe 100644 --- a/examples/candle_whisper/Cargo.toml +++ b/examples/candle_whisper/Cargo.toml @@ -21,7 +21,7 @@ bindgen_cuda = { version = "0.1.5", optional = true } [dependencies] -clap = { version = "4.5.7", features = ["derive"] } +clap = { version = "4.5.8", features = ["derive"] } serde = { version = "1.0", features = ["derive"] } silent = { path = "../../silent", features = ["multipart"] } symphonia = { version = "0.5.4", features = ["all"] } @@ -38,5 +38,5 @@ candle-transformers = { git = "https://github.com/huggingface/candle" } tokenizers = { version = "0.19.1", features = ["onig"] } rand = "0.8.5" -serde_json = "1.0.117" +serde_json = "1.0.120" byteorder = "1.5.0" diff --git a/examples/configs/Cargo.toml b/examples/configs/Cargo.toml index fcdf4b4..122382a 100644 --- a/examples/configs/Cargo.toml +++ b/examples/configs/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } -async-trait = "0.1.80" +async-trait = "0.1.81" diff --git a/examples/custom_handler/Cargo.toml b/examples/custom_handler/Cargo.toml index f7d959d..1e23cf9 100644 --- a/examples/custom_handler/Cargo.toml +++ b/examples/custom_handler/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } -async-trait = "0.1.80" +async-trait = "0.1.81" diff --git a/examples/custom_tokio_listener/Cargo.toml b/examples/custom_tokio_listener/Cargo.toml index 58527bc..a4ed39b 100644 --- a/examples/custom_tokio_listener/Cargo.toml +++ b/examples/custom_tokio_listener/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } -async-trait = "0.1.80" +async-trait = "0.1.81" tokio = { version = "1.38.0", features = ["full"] } diff --git a/examples/custom_tokio_runtime/Cargo.toml b/examples/custom_tokio_runtime/Cargo.toml index 58c97d0..6b3d06f 100644 --- a/examples/custom_tokio_runtime/Cargo.toml +++ b/examples/custom_tokio_runtime/Cargo.toml @@ -7,5 +7,5 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } -async-trait = "0.1.80" +async-trait = "0.1.81" tokio = { version = "1.38.0", features = ["full"] } diff --git a/examples/exception_handler/Cargo.toml b/examples/exception_handler/Cargo.toml index 41ee57b..b59ea75 100644 --- a/examples/exception_handler/Cargo.toml +++ b/examples/exception_handler/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } -serde = { version = "1.0.203", features = ["derive"] } +serde = { version = "1.0.204", features = ["derive"] } diff --git a/examples/form/Cargo.toml b/examples/form/Cargo.toml index 7938132..6e8c97e 100644 --- a/examples/form/Cargo.toml +++ b/examples/form/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } -serde = { version = "1.0.203", features = ["derive"] } +serde = { version = "1.0.204", features = ["derive"] } diff --git a/examples/grpc/Cargo.toml b/examples/grpc/Cargo.toml index 8bd9c4b..6cdc549 100644 --- a/examples/grpc/Cargo.toml +++ b/examples/grpc/Cargo.toml @@ -13,11 +13,11 @@ name = "example-grpc-client" path = "src/client.rs" [dependencies] -tonic = { git = "https://github.com/hyperium/tonic" } -prost = "0.12" +tonic = { version = "0.12.0" } +prost = "0.13" tokio = { version = "1.38", features = ["macros", "rt-multi-thread"] } silent = { path = "../../silent", features = ["grpc"] } -async-trait = "0.1.80" +async-trait = "0.1.81" [build-dependencies] -tonic-build = { git = "https://github.com/alexrudy/tonic", branch = "hyper-1.0" } +tonic-build = { version = "0.12.0" } diff --git a/examples/grpc_h2c/Cargo.toml b/examples/grpc_h2c/Cargo.toml index 7cd0f6a..e0ab7f4 100644 --- a/examples/grpc_h2c/Cargo.toml +++ b/examples/grpc_h2c/Cargo.toml @@ -13,11 +13,11 @@ name = "example-grpc-client" path = "src/client.rs" [dependencies] -tonic = { git = "https://github.com/hyperium/tonic" } -prost = "0.12" +tonic = { version = "0.12.0" } +prost = "0.13" tokio = { version = "1.38", features = ["macros", "rt-multi-thread"] } silent = { path = "../../silent", features = ["grpc"] } -async-trait = "0.1.80" +async-trait = "0.1.81" [build-dependencies] -tonic-build = { git = "https://github.com/hyperium/tonic" } +tonic-build = { version = "0.12.0" } diff --git a/examples/grpc_streaming/Cargo.toml b/examples/grpc_streaming/Cargo.toml index 9922214..7827562 100644 --- a/examples/grpc_streaming/Cargo.toml +++ b/examples/grpc_streaming/Cargo.toml @@ -13,13 +13,13 @@ name = "example-grpc-client" path = "src/client.rs" [dependencies] -tonic = { git = "https://github.com/hyperium/tonic" } -prost = "0.12" +tonic = { version = "0.12.0" } +prost = "0.13" tokio = { version = "1.38", features = ["macros", "rt-multi-thread"] } silent = { path = "../../silent", features = ["grpc"] } -async-trait = "0.1.80" +async-trait = "0.1.81" tokio-stream = "0.1.15" h2 = "0.4.5" [build-dependencies] -tonic-build = { git = "https://github.com/hyperium/tonic" } +tonic-build = { version = "0.12.0" } diff --git a/examples/middleware/Cargo.toml b/examples/middleware/Cargo.toml index 84306c8..d5491ff 100644 --- a/examples/middleware/Cargo.toml +++ b/examples/middleware/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-trait = "0.1.80" +async-trait = "0.1.81" silent = { path = "../../silent" } diff --git a/examples/multipart-form/Cargo.toml b/examples/multipart-form/Cargo.toml index 9d36b9e..5d86711 100644 --- a/examples/multipart-form/Cargo.toml +++ b/examples/multipart-form/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" [dependencies] silent = { path = "../../silent", features = ["multipart"] } -serde = { version = "1.0.203", features = ["derive"] } +serde = { version = "1.0.204", features = ["derive"] } diff --git a/examples/sse-chat/Cargo.toml b/examples/sse-chat/Cargo.toml index ac0b336..ef13a5d 100644 --- a/examples/sse-chat/Cargo.toml +++ b/examples/sse-chat/Cargo.toml @@ -11,4 +11,4 @@ once_cell = "1" parking_lot = "0.12" tokio = { version = "1", features = ["macros"] } tokio-stream = { version = "0.1", features = ["net"] } -serde = { version = "1.0.203", features = ["derive"] } +serde = { version = "1.0.204", features = ["derive"] } diff --git a/examples/templates/Cargo.toml b/examples/templates/Cargo.toml index 75350c9..1490b1a 100644 --- a/examples/templates/Cargo.toml +++ b/examples/templates/Cargo.toml @@ -6,5 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde = { version = "1.0.203", features = ["derive"] } +serde = { version = "1.0.204", features = ["derive"] } silent = { path = "../../silent", features = ["template"] } diff --git a/examples/todo/Cargo.toml b/examples/todo/Cargo.toml index cdff445..aecf818 100644 --- a/examples/todo/Cargo.toml +++ b/examples/todo/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" [dependencies] silent = { path = "../../silent" } -serde = { version = "1.0.203", features = ["derive"] } -uuid = { version = "1.8.0", features = ["serde", "v4"] } -async-trait = "0.1.80" +serde = { version = "1.0.204", features = ["derive"] } +uuid = { version = "1.9.1", features = ["serde", "v4"] } +async-trait = "0.1.81" diff --git a/examples/websocket/Cargo.toml b/examples/websocket/Cargo.toml index 9a6fec1..0f006a6 100644 --- a/examples/websocket/Cargo.toml +++ b/examples/websocket/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-trait = "0.1.80" +async-trait = "0.1.81" silent = { path = "../../silent", features = ["upgrade"] } tokio = { version = "1.38.0", features = ["full"] } -tokio-tungstenite = "0.23.0" +tokio-tungstenite = "0.23.1" futures-util = "0.3.30" backtrace = "0.3.73" headers = "0.4.0" diff --git a/silent/Cargo.toml b/silent/Cargo.toml index 2a7538e..6b04012 100644 --- a/silent/Cargo.toml +++ b/silent/Cargo.toml @@ -35,23 +35,23 @@ grpc = ["upgrade", "dep:tonic", "dep:pin-project-lite", "dep:pin-project", "dep: [dependencies] # Basic dependencies thiserror = "1.0.61" -hyper = { version = "1.3.1", features = ["full"] } -hyper-util = { version = "0.1.5", features = ["server-auto", "tokio"] } +hyper = { version = "1.4.0", features = ["full"] } +hyper-util = { version = "0.1.6", features = ["server-auto", "tokio"] } tokio = { version = "1.38.0", optional = true } bytes = "1.6.0" http-body-util = "0.1.2" tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["local-time"] } -async-trait = "0.1.80" -serde = { version = "1.0.203", features = ["derive"] } -serde_json = "1.0.117" -uuid = "1.8.0" -url = "2.5.1" +async-trait = "0.1.81" +serde = { version = "1.0.204", features = ["derive"] } +serde_json = "1.0.120" +uuid = "1.9.1" +url = "2.5.2" serde_urlencoded = "0.7.1" mime = "0.3.17" futures-util = "0.3.30" chrono = { version = "0.4.38", default-features = false, features = ["clock"] } -tokio-tungstenite = { version = "0.23.0", optional = true } +tokio-tungstenite = { version = "0.23.1", optional = true } headers = "0.4.0" tokio-stream = { version = "0.1.15", features = ["net"], optional = true } pin-project = { version = "1.1", optional = true } @@ -80,7 +80,7 @@ async-session = { version = "3.0.0", optional = true } cookie = { version = "0.18.1", features = ["secure", "percent-encode"], optional = true } # Grpc -tonic = { git = "https://github.com/hyperium/tonic", optional = true } +tonic = { version = "0.12.0", optional = true } # Security argon2 = { version = "0.5.3", optional = true } @@ -88,4 +88,4 @@ pbkdf2 = { version = "0.12", features = ["simple"], optional = true } aes-gcm = { version = "0.10.3", optional = true } aes = { version = "0.8", optional = true } rsa = { version = "0.9.6", optional = true } -mime_guess = "2.0.4" +mime_guess = "2.0.5"