The web content describes the creation of a real-time chat system using Rust and gRPC-web for the backend and frontend communication, respectively, with Protobuf for message definition and Envoy as a proxy for gRPC-web compatibility.
Abstract
The article outlines the development of a broadcast chat room utilizing Rust and gRPC-web for efficient and safe backend and frontend communication. It leverages Protobuf for message structuring, Tonic as the Rust gRPC framework, and Envoy as a proxy to enable gRPC-web functionality. The system is designed to be scalable and serves as a demonstration of how to use Rust with gRPC as a backend and gRPC-web for frontend messaging API, diverging from the traditional RESTful approach. The author provides a detailed guide, including the folder structure, Protobuf message definitions, backend server setup with Tonic, and frontend integration with gRPC-web. The source code for the project is made publicly available on GitHub.
Opinions
The author believes that Rust is a superior choice for the backend due to its safety, speed, and static nature, complemented by gRPC's efficiency.
The article suggests that using Rust and gRPC for a web chat system is a modern and efficient approach, emphasizing the benefits of static typing and compiler error checking.
The author implies that the combination of Rust, gRPC, and gRPC-web can lead to a robust and performant chat system that can be extended for larger applications.
By skipping a lengthy introduction to the tools used, the author indicates a preference for a concise and practical presentation, targeting readers already familiar with or interested in these technologies.
The author points out the limitation of gRPC-web not supporting bidirectional streaming and proposes a workaround using unary RPC for message sending.
The author highlights the effectiveness of the Rust compiler in catching errors, suggesting that it leads to more reliable code and a faster development process once the language's unique features are mastered.
The article concludes with a nod to future enhancements, such as implementing JWT authentication, to improve the chat system's security and functionality.
Chat System by Rust and gRPC-Web
Using Tonic as backend and gRPC-web as frontend communication to build chat system. Protobuf + gRPC + rust/tonic + envoy + gRPC-web.
Image by Author
Background
Rust is static, fast, and safe. gRPC is static and popular as well. Why cannot we try to use Rust + gRPC to create a web-chatting system? To make this article simple and quick to read. I will skip the background introduction, please read the below links if you are interested for tools used here:
Rust, the programming language for our backend system.
gRPC-web, gRPC for web since browser didn’t support HTTP2.
Javascript + HTML for showing content on frontend.
What we will do
We will create a broadcast chatting room for everyone. There are lots of tutorials doing this, but what are the differences here? We will demo how to use Rust with gRPC as backend, and use gRPC-web as frontend msg API instead of RESTful. After having this system, we could extend it to a larger size. Souce code is published at marshal-shi/tonic-gRPC-web-chat
Folder Structure:
protos: define protobuf messages and services
backend: use tonic as chat backend system.
frontend: grpc-web talk to backend. Insert js into index.html for demo.
Image by Author
Protobuf Message Definition
Use protobuf v3 to define our messages.
Backend
Rust has a very good gRPC backend framework: Tonic. Tonic is fast, even compared with C/C++, see this post. SO, we will use Tonic as our backend server.
Because there are tutorials talking about how to set up Rust crates by cargo, I will skip it and directly start with Tonic. To setup Tonic with protobuf. We named our crate as backend. Create build.rs file under crate home folder:
Now we can build our code, you will see there is a chat.rs file under target/debug/build/backend-77315cab1bea1b1f/out/ folder. (Here the folder number may be different on your computer).
Image by Author
After we know that the protobuf related *.rs file is good, we can start programming our server.
Import our compiled protobuf rs file.
2. We will create a `Shared` data struct to hold user and its channel sender. And it will be shared to all users.
3. Server stream to frontend
4. Since gRPC-web didn’t support Bidirectional streaming, we will use an unary rpc to send new msgs.
5. gRPC-web needs a proxy to translate into gRPC. Envoy has native support for this, and the following configuration example for Envoy does exactly that. Please check the code here to view the YAML settings file.
Frontend
Based on the explanation in gRPC-web, we need to compile protobuf to Javascript such that our JS code is able to use our message types.
After the target `.js` file is generated, we can use it in our code in following steps: (Won’t copy/paste code to here. Please check source code at repo/frontend)
Require generated js files.
Request to connect server for server steaming.
Sending a single message from frontend to backend.
We are using JS code to append new elements to chatting history. Please check 2 step.
Open index.html page in your browser. (You may got domain issue when visiting page, disable security to access chromium --disable-web-security --disable-gpu --user-data-dir=./chrometest)
How it looks
We have linked the backend Tonic and frontend gRPC-web and messages are displaying well. Below is the image showing how it works.
Next step and Conclusion
This tutorial quickly shows how we can do gRPC in Rust and link to the frontend. If we have an IOS or android app, we could have a cross-platform chatting system. But we didn’t do authorization, what we should do next step. Please check JWT authentication in Rust [https://blog.logrocket.com/jwt-authentication-in-rust/] for more details about JWT.
Rust is fast and safe. In the beginning, it will take time to understand ownership and its syntax. But after being familiar with it, I felt it’s much faster than coding in Python. The reason is we don’t need to do “useless” type checking in code and most of the errors are captured by the compiler. After compiling successfully, 90% chance our code is good to run.