pub struct GenericGrpcService { /* private fields */ }Expand description
Generic gRPC service that routes requests to a GrpcHandler
This service implements Tonic’s server traits and routes all requests to the provided GrpcHandler implementation. It handles serialization at the boundary between Tonic and our handler trait.
§Example
use spikard_http::grpc::service::GenericGrpcService;
use std::sync::Arc;
let handler = Arc::new(MyGrpcHandler);
let service = GenericGrpcService::new(handler);Implementations§
Source§impl GenericGrpcService
impl GenericGrpcService
Sourcepub fn new(handler: Arc<dyn GrpcHandler>) -> Self
pub fn new(handler: Arc<dyn GrpcHandler>) -> Self
Create a new generic gRPC service with the given handler
Sourcepub async fn handle_unary(
&self,
service_name: String,
method_name: String,
request: Request<Bytes>,
) -> Result<Response<Bytes>, Status>
pub async fn handle_unary( &self, service_name: String, method_name: String, request: Request<Bytes>, ) -> Result<Response<Bytes>, Status>
Handle a unary RPC call
Converts the Tonic Request into our GrpcRequestData format, calls the handler, and converts the result back to a Tonic Response.
§Arguments
service_name- Fully qualified service namemethod_name- Method namerequest- Tonic request containing the serialized protobuf message
Sourcepub async fn handle_server_stream(
&self,
service_name: String,
method_name: String,
request: Request<Bytes>,
) -> Result<Response<Body>, Status>
pub async fn handle_server_stream( &self, service_name: String, method_name: String, request: Request<Bytes>, ) -> Result<Response<Body>, Status>
Handle a server streaming RPC call
Takes a single request and returns a stream of response messages. Converts the Tonic Request into our GrpcRequestData format, calls the handler’s call_server_stream method, and converts the MessageStream into a Tonic streaming response body.
§Arguments
service_name- Fully qualified service namemethod_name- Method namerequest- Tonic request containing the serialized protobuf message
§Returns
A Response with a streaming body containing the message stream
§Error Propagation Limitations
When a stream returns an error mid-stream (after messages have begun
being sent), the error may not be perfectly transmitted to the client
as a gRPC trailer. This is due to limitations in Axum’s Body::from_stream:
- Pre-stream errors (before any messages): Properly converted to HTTP status codes and returned to the client
- Mid-stream errors (after messages have begun): The error is converted
to a generic
BoxError, and the stream terminates. The connection is properly closed, but the gRPC status code metadata is lost.
For robust error handling in streaming RPCs:
- Prefer detecting errors early (before sending messages) when possible
- Include error information in the message stream itself if critical (application-level error messages in the protobuf)
- For true gRPC trailer support, consider implementing a custom Axum body type that wraps the stream and can inject trailers on error
Sourcepub async fn handle_client_stream(
&self,
service_name: String,
method_name: String,
request: Request<Body>,
max_message_size: usize,
) -> Result<Response<Bytes>, Status>
pub async fn handle_client_stream( &self, service_name: String, method_name: String, request: Request<Body>, max_message_size: usize, ) -> Result<Response<Bytes>, Status>
Handle a client streaming RPC call
Takes a request body stream of protobuf messages and returns a single response. Parses the HTTP/2 body stream using gRPC frame parser, creates a MessageStream, calls the handler’s call_client_stream method, and converts the GrpcResponseData back to a Tonic Response.
§Arguments
service_name- Fully qualified service namemethod_name- Method namerequest- Axum request with streaming body containing HTTP/2 framed protobuf messagesmax_message_size- Maximum size per message (bytes)
§Returns
A Response with a single message body
§Stream Handling
The request body stream contains framed protobuf messages. Each frame is parsed and validated for size:
- Messages within
max_message_sizeare passed to the handler - Messages exceeding the limit result in a ResourceExhausted error
- Invalid frames result in InvalidArgument errors
- The stream terminates when the client closes the write side
§Frame Format
Frames follow the gRPC HTTP/2 protocol format:
- 1 byte: compression flag (0 = uncompressed)
- 4 bytes: message size (big-endian)
- N bytes: message payload
§Metadata and Trailers
- Request metadata (headers) from the Tonic request is passed to the handler
- Response metadata from the handler is included in the response headers
- gRPC trailers (like grpc-status) should be handled by the caller
Sourcepub async fn handle_bidi_stream(
&self,
service_name: String,
method_name: String,
request: Request<Body>,
max_message_size: usize,
) -> Result<Response<Body>, Status>
pub async fn handle_bidi_stream( &self, service_name: String, method_name: String, request: Request<Body>, max_message_size: usize, ) -> Result<Response<Body>, Status>
Handle a bidirectional streaming RPC call
Takes a request body stream and returns a stream of response messages. Parses the HTTP/2 body stream using gRPC frame parser, creates a StreamingRequest, calls the handler’s call_bidi_stream method, and converts the MessageStream back to an Axum streaming response body.
§Arguments
service_name- Fully qualified service namemethod_name- Method namerequest- Axum request with streaming body containing HTTP/2 framed protobuf messagesmax_message_size- Maximum size per message (bytes)
§Returns
A Response with a streaming body containing response messages
§Stream Handling
- Request stream: Parsed from HTTP/2 body using frame parser
- Response stream: Converted from MessageStream to Axum Body
- Both streams are independent (full-duplex)
- Errors in either stream are propagated appropriately
§Error Propagation
Similar to server streaming, mid-stream errors in the response may not be perfectly transmitted as gRPC trailers due to Axum Body::from_stream limitations. See handle_server_stream() documentation for details.
Sourcepub fn service_name(&self) -> &str
pub fn service_name(&self) -> &str
Get the service name from the handler
Auto Trait Implementations§
impl Freeze for GenericGrpcService
impl !RefUnwindSafe for GenericGrpcService
impl Send for GenericGrpcService
impl Sync for GenericGrpcService
impl Unpin for GenericGrpcService
impl !UnwindSafe for GenericGrpcService
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::RequestSource§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);