Rustgrpc
Rustgrpc
Using gRPC in Rust, while learning the basics of Tonic and protobuffers.
Well what is a protobuf?
Protobuffers are a way of encoding structured data in a text format, used in many different programming languages. They are a popular alternative to JSON and YAML, which are used in REST APIs.
According to Google:
Protocol buffers are a Language-Neutral, platform-neutral, Protobuf is a data interchange format and language for structured data. It’s like JSON, but smaller and faster.
Protobuf Syntax overview
When defining fields in .proto
files, it is possible to set if the field is optional or not, or repeated.
A field can also be:
- message
- enum
- oneof
- map
One basic example is:
message User {
int64 id = 1;
string name = 2;
}
Implementing a basic example: “GreetingRust”
- Create a new project with cargo
cargo new GreetingRust
- Add the following dependencies
cargo add tonic
- Create the
.proto
inside a folder
mkdir src
touch src/greet.proto
- Add the
.proto
file
syntax = "proto3";
import "greet.proto";
service GreetService {
rpc Greet (GreetRequest) returns (GreetResponse);
}
- Create the
src/greet.proto
file
syntax = "proto3";
message GreetRequest {
string name = 1;
}
message GreetResponse {
string message = 1;
}
- Create the
src/greet.rs
file
use tonic::transport::Server;
use tonic::{Request, Response, Status};
use greet::greet_server::{Greet, GreetServer};
use greet::GreetRequest;
use greet::GreetResponse;
#[derive(Debug)]
pub struct MyGreet {}
#[tonic::async_trait]
impl Greet for MyGreet {
async fn greet(&self, request: Request<GreetRequest>) -> Result<Response<GreetResponse>, Status> {
println!("Got a request: {:?}", request);
let response = GreetResponse {
message: format!("Hello {}!", request.into_inner().name),
};
Ok(Response::new(response))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:50051".parse()?;
let greeter = MyGreet {};
Server::builder()
.add_service(GreetServer::new(greeter))
.serve(addr)
.await?;
Ok(())
}
- Run the code
cargo run
- Create a client and send a request
use greet::greet_client::GreetClient;
use greet::GreetRequest;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = GreetClient::connect("http://[::1]:50051").await?;
let request = tonic::Request::new(GreetRequest {
name: "Diogo".to_string(),
});
let response = client.greet(request).await?;
println!("RESPONSE={:?}", response);
Ok(())
}