pub struct Router { /* private fields */ }Expand description
Router for ConnectRPC services.
The router maps service/method paths to their handlers and manages request dispatching.
Router is the dynamic dispatch path: method paths are owned String
keys. It can still carry a Spec when one is attached with
with_spec — the generated
FooServiceExt::register does this for every method, so a Router
built through codegen surfaces RequestContext::spec just like the
monomorphic FooServiceServer<T> dispatcher does. Hand-written
route_* registrations without a Spec surface None.
Implementations§
Source§impl Router
impl Router
Sourcepub fn route<H, Req, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Self
pub fn route<H, Req, Res>( self, service_name: &str, method_name: &str, handler: H, ) -> Self
Register a unary RPC handler.
§Arguments
service_name- The fully qualified service name (e.g., “example.v1.GreetService”)method_name- The method name (e.g., “Greet”)handler- The handler function or closure
§Example
let router = Router::new()
.route("example.v1.GreetService", "Greet", |ctx, req: GreetRequest| async move {
Ok(GreetResponse { message: format!("Hello, {}!", req.name) })
});Sourcepub fn route_idempotent<H, Req, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Self
pub fn route_idempotent<H, Req, Res>( self, service_name: &str, method_name: &str, handler: H, ) -> Self
Register an idempotent unary RPC handler that supports GET requests.
Idempotent methods have no side effects and can be called via HTTP GET.
This is typically used for methods marked with idempotency_level = NO_SIDE_EFFECTS
in the protobuf definition.
§Arguments
service_name- The fully qualified service name (e.g., “example.v1.GreetService”)method_name- The method name (e.g., “Greet”)handler- The handler function or closure
§Example
let router = Router::new()
.route_idempotent("example.v1.QueryService", "GetUser", |ctx, req: GetUserRequest| async move {
Ok(GetUserResponse { ... })
});Sourcepub fn route_server_stream<H, Req, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: StreamingHandler<Req, Res>,
Req: Message + DeserializeOwned + Send + 'static,
Res: Message + Send + 'static,
pub fn route_server_stream<H, Req, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: StreamingHandler<Req, Res>,
Req: Message + DeserializeOwned + Send + 'static,
Res: Message + Send + 'static,
Register a server streaming RPC handler.
A server streaming handler takes a single request and returns a stream of responses.
§Arguments
service_name- The fully qualified service name (e.g., “example.v1.GreetService”)method_name- The method name (e.g., “GreetMany”)handler- The streaming handler function or closure
§Example
let router = Router::new()
.route_server_stream("example.v1.GreetService", "GreetMany", streaming_handler_fn(my_handler));Sourcepub fn route_client_stream<H, Req, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ClientStreamingHandler<Req, Res>,
Req: Message + DeserializeOwned + Send + 'static,
Res: Message + Serialize + Send + 'static,
pub fn route_client_stream<H, Req, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ClientStreamingHandler<Req, Res>,
Req: Message + DeserializeOwned + Send + 'static,
Res: Message + Serialize + Send + 'static,
Register a client streaming RPC handler.
A client streaming handler receives a stream of requests and returns a single response.
Sourcepub fn route_bidi_stream<H, Req, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: BidiStreamingHandler<Req, Res>,
Req: Message + DeserializeOwned + Send + 'static,
Res: Message + Send + 'static,
pub fn route_bidi_stream<H, Req, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: BidiStreamingHandler<Req, Res>,
Req: Message + DeserializeOwned + Send + 'static,
Res: Message + Send + 'static,
Register a bidi streaming RPC handler.
A bidi streaming handler receives a stream of requests and returns a stream of responses.
Sourcepub fn route_view<H, ReqView>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ViewHandler<ReqView>,
ReqView: MessageView<'static> + Send + Sync + 'static,
ReqView::Owned: Message + DeserializeOwned,
pub fn route_view<H, ReqView>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ViewHandler<ReqView>,
ReqView: MessageView<'static> + Send + Sync + 'static,
ReqView::Owned: Message + DeserializeOwned,
Register a unary RPC handler that uses zero-copy request views.
Sourcepub fn route_view_idempotent<H, ReqView>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ViewHandler<ReqView>,
ReqView: MessageView<'static> + Send + Sync + 'static,
ReqView::Owned: Message + DeserializeOwned,
pub fn route_view_idempotent<H, ReqView>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ViewHandler<ReqView>,
ReqView: MessageView<'static> + Send + Sync + 'static,
ReqView::Owned: Message + DeserializeOwned,
Register an idempotent unary RPC handler that uses zero-copy request views.
Sourcepub fn route_view_server_stream<H, ReqView, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ViewStreamingHandler<ReqView, Res>,
ReqView: MessageView<'static> + Send + Sync + 'static,
ReqView::Owned: Message + DeserializeOwned,
Res: Message + Send + 'static,
pub fn route_view_server_stream<H, ReqView, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ViewStreamingHandler<ReqView, Res>,
ReqView: MessageView<'static> + Send + Sync + 'static,
ReqView::Owned: Message + DeserializeOwned,
Res: Message + Send + 'static,
Register a server streaming RPC handler that uses zero-copy request views.
Sourcepub fn route_view_client_stream<H, ReqView>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ViewClientStreamingHandler<ReqView>,
ReqView: MessageView<'static> + Send + Sync + 'static,
ReqView::Owned: Message + DeserializeOwned,
pub fn route_view_client_stream<H, ReqView>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ViewClientStreamingHandler<ReqView>,
ReqView: MessageView<'static> + Send + Sync + 'static,
ReqView::Owned: Message + DeserializeOwned,
Register a client streaming RPC handler that uses zero-copy request views.
Sourcepub fn route_view_bidi_stream<H, ReqView, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ViewBidiStreamingHandler<ReqView, Res>,
ReqView: MessageView<'static> + Send + Sync + 'static,
ReqView::Owned: Message + DeserializeOwned,
Res: Message + Send + 'static,
pub fn route_view_bidi_stream<H, ReqView, Res>(
self,
service_name: &str,
method_name: &str,
handler: H,
) -> Selfwhere
H: ViewBidiStreamingHandler<ReqView, Res>,
ReqView: MessageView<'static> + Send + Sync + 'static,
ReqView::Owned: Message + DeserializeOwned,
Res: Message + Send + 'static,
Register a bidi streaming RPC handler that uses zero-copy request views.
Sourcepub fn with_spec(self, spec: Spec) -> Self
pub fn with_spec(self, spec: Spec) -> Self
Attach a Spec to the route registered at spec.procedure.
The route must already exist — Spec::procedure is the lookup
key (with the leading slash stripped, matching the route_*
methods’ format!("{service}/{method}") keying). Generated
FooServiceExt::register chains this after each route_view*
call so the dynamic Router carries the same per-method
metadata as the monomorphic FooServiceServer<T>. Hand-written
registrations may call it too when they have a &'static
procedure path:
const SAY_SPEC: Spec = Spec::server("/eliza.v1.Eliza/Say", StreamType::Unary);
let router = Router::new()
.route_view_idempotent("eliza.v1.Eliza", "Say", handler)
.with_spec(SAY_SPEC);§Panics
Debug builds panic if no route is registered at spec.procedure,
or if the route is unary and spec.idempotency_level disagrees
with the route / route_idempotent choice. Both indicate a
programming error in register() (a typo, or calling with_spec
before the matching route_*); release builds skip the check and
silently drop the Spec.
Sourcepub fn has_method(&self, path: &str) -> bool
pub fn has_method(&self, path: &str) -> bool
Check if a path is registered.
Source§impl Router
impl Router
Sourcepub fn into_axum_service(self) -> ConnectRpcService
Available on crate feature axum only.
pub fn into_axum_service(self) -> ConnectRpcService
axum only.Convert this ConnectRPC router into an axum Router.
The returned router handles all ConnectRPC paths registered with this router. It can be merged with other axum routes or used as a fallback.
§Example
use axum::{Router, routing::get};
use connectrpc::Router as ConnectRouter;
async fn health() -> &'static str {
"OK"
}
let connect_router = ConnectRouter::new()
.route("example.v1.GreetService", "Greet", greet_handler);
let app = Router::new()
.route("/health", get(health))
.fallback_service(connect_router.into_axum_service());Sourcepub fn into_axum_router(self) -> Router
Available on crate feature axum only.
pub fn into_axum_router(self) -> Router
axum only.Create an axum Router with the ConnectRPC handlers.
This creates a catch-all route that handles all paths. Use this
with Router::merge() or Router::fallback().
§Example
use axum::{Router, routing::get};
use connectrpc::Router as ConnectRouter;
let connect_router = ConnectRouter::new()
.route("example.v1.GreetService", "Greet", greet_handler);
// Use as fallback for unmatched routes
let app = Router::new()
.route("/health", get(health))
.fallback_service(connect_router.into_axum_service());Trait Implementations§
Source§impl Dispatcher for Router
impl Dispatcher for Router
Source§fn lookup(&self, path: &str) -> Option<MethodDescriptor>
fn lookup(&self, path: &str) -> Option<MethodDescriptor>
service_name/method_name path. Read more