gRPC
Basic implementation that currently only supports unary calls. gRPC is an high-performance remote procedure call framework developed by Google that enables efficient communication between distributed systems, particularly in microservices architectures.
wtx does not provide built-in deserialization or serialization utilities capable of manipulate protobuf files. Instead, users are free to choose any third-party that generates Rust bindings and implements the internal Deserialize and Serialize traits.
Due to the lack of an official parser, the definitions of a Service must be manually typed.
Independent benchmarks are available at https://github.com/LesnyRumcajs/grpc_bench.
Client Example
To use this functionality, it is necessary to activate the grpc-client feature.
//! gRPC client that uses the structure definitions found in the `wtx_instances::grpc_bindings`
//! module.
extern crate tokio;
extern crate wtx;
extern crate wtx_examples;
use std::borrow::Cow;
use wtx::{
codec::format::QuickProtobuf,
grpc::GrpcClient,
http::{MsgBufferStr, http2_client_pool::Http2ClientPoolBuilder},
tls::TlsConfig,
};
use wtx_examples::{
ROOT_CA,
grpc_bindings::wtx::{GenericRequest, GenericResponse},
};
#[tokio::main]
async fn main() -> wtx::Result<()> {
let uri = "https://127.0.0.1:9000/wtx.GenericService/generic_method";
let mut client = GrpcClient::new(
Http2ClientPoolBuilder::tokio(1, TlsConfig::from_trust_anchors_pem([ROOT_CA])?)?.build(),
QuickProtobuf,
);
let res = client
.send_unary_req(
GenericRequest {
generic_request_field0: Cow::Borrowed(b"generic_request_value"),
generic_request_field1: 123,
},
MsgBufferStr::from_uri(uri.into()),
)
.await?;
let generic_response: GenericResponse = client.des_from_res_bytes(&res.msg_data.body)?;
println!("{generic_response:?}");
Ok(())
}
Server Example
To use this functionality, it is necessary to activate the grpc-server feature.
//! gRPC server that uses the structure definitions found in the `wtx_instances::grpc_bindings`
//! module.
extern crate tokio;
extern crate wtx;
extern crate wtx_examples;
use std::borrow::Cow;
use wtx::{
codec::format::QuickProtobuf,
executor::TokioExecutor,
grpc::{GrpcManager, GrpcMiddleware},
http::{
StatusCode,
http2_server_framework::{Http2ServerFramework, HttpRouter, State, post},
},
rng::{ChaCha20, CryptoSeedableRng},
tls::TlsConfig,
};
use wtx_examples::{
PUBLIC_KEY, SECRET_KEY,
grpc_bindings::wtx::{GenericRequest, GenericResponse},
host_from_args,
};
fn main() -> wtx::Result<()> {
let mut rng = ChaCha20::from_getrandom()?;
let tls_config = TlsConfig::from_keys_pem(PUBLIC_KEY.try_into()?, &mut rng, SECRET_KEY)?;
let router = HttpRouter::new(
wtx::paths!(("wtx.GenericService/generic_method", post(wtx_generic_service_generic_method))),
GrpcMiddleware,
)?;
Http2ServerFramework::new(TokioExecutor::default(), rng, tls_config)?
.set_data(GrpcManager::from_drsr(QuickProtobuf))
.set_error_cb(|err| eprintln!("Error: {err}"))
.run_in_threads(&host_from_args(), router)
}
async fn wtx_generic_service_generic_method(
state: State<'_, GrpcManager<QuickProtobuf>>,
) -> wtx::Result<StatusCode> {
let _generic_request: GenericRequest = state.data.des_from_req_bytes(&state.req.msg_data.body)?;
state.req.clear();
state.data.ser_to_res_bytes(
&mut state.req.msg_data.body,
GenericResponse {
generic_response_field0: Cow::Borrowed(b"generic_response_value"),
generic_response_field1: 321,
},
)?;
Ok(StatusCode::Ok)
}